diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 67420d24..dae36adc 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). The format of this change log follows the advice given at [Keep a CHANGELOG](http://keepachangelog.com). ## [Unreleased] +### Added +- Added support for the `--tags` and `--name` options into the `behat` command. + ### Changed - ACTION SUGGESTED: If you are using GitHub Actions, it's recomended to use `!cancelled()` instead of `always()` for moodle-plugin-ci tests. Adding a final step that always returns failure when the workflow is cancelled will ensure that cancelled workflows are not marked as successful. For a working example, please reference the updated `gha.dist.yml` file. - ACTION SUGGESTED: For some (unknown) reason, Travis environments with PHP 8.2 have started to fail with error: diff --git a/docs/CLI.md b/docs/CLI.md index b7bb9c47..1507eab6 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -241,7 +241,7 @@ Run Behat on a plugin ### Usage -* `behat [-m|--moodle MOODLE] [-p|--profile PROFILE] [--suite SUITE] [--start-servers] [--auto-rerun AUTO-RERUN] [--dump] [--] ` +* `behat [-m|--moodle MOODLE] [-p|--profile PROFILE] [--suite SUITE] [--tags TAGS] [--name NAME] [--start-servers] [--auto-rerun AUTO-RERUN] [--dump] [--] ` Run Behat on a plugin @@ -269,7 +269,7 @@ Path to Moodle #### `--profile|-p` -Behat profile to use +Behat profile option to use * Accept value: yes * Is value required: yes @@ -279,7 +279,7 @@ Behat profile to use #### `--suite` -Behat suite to use (Moodle theme) +Behat suite option to use (Moodle theme) * Accept value: yes * Is value required: yes @@ -287,6 +287,26 @@ Behat suite to use (Moodle theme) * Is negatable: no * Default: `'default'` +#### `--tags` + +Behat tags option to use. If not set, defaults to the component name + +* Accept value: yes +* Is value required: yes +* Is multiple: no +* Is negatable: no +* Default: `''` + +#### `--name` + +Behat name option to use + +* Accept value: yes +* Is value required: yes +* Is multiple: no +* Is negatable: no +* Default: `''` + #### `--start-servers` Start Selenium and PHP servers diff --git a/src/Command/BehatCommand.php b/src/Command/BehatCommand.php index 94171b36..aeeecd99 100644 --- a/src/Command/BehatCommand.php +++ b/src/Command/BehatCommand.php @@ -58,8 +58,11 @@ protected function configure(): void parent::configure(); $this->setName('behat') - ->addOption('profile', 'p', InputOption::VALUE_REQUIRED, 'Behat profile to use', 'default') - ->addOption('suite', null, InputOption::VALUE_REQUIRED, 'Behat suite to use (Moodle theme)', 'default') + ->addOption('profile', 'p', InputOption::VALUE_REQUIRED, 'Behat profile option to use', 'default') + ->addOption('suite', null, InputOption::VALUE_REQUIRED, 'Behat suite option to use (Moodle theme)', 'default') + ->addOption('tags', null, InputOption::VALUE_REQUIRED, 'Behat tags option to use. ' . + 'If not set, defaults to the component name', '') + ->addOption('name', null, InputOption::VALUE_REQUIRED, 'Behat name option to use', '') ->addOption('start-servers', null, InputOption::VALUE_NONE, 'Start Selenium and PHP servers') ->addOption('auto-rerun', null, InputOption::VALUE_REQUIRED, 'Number of times to rerun failures', 2) ->addOption('dump', null, InputOption::VALUE_NONE, 'Print contents of Behat failure HTML files') @@ -89,14 +92,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int $cmd = [ 'php', 'admin/tool/behat/cli/run.php', - '--tags=@' . $this->plugin->getComponent(), '--profile=' . $input->getOption('profile'), '--suite=' . $input->getOption('suite'), + '--tags=' . ($input->getOption('tags') ?: '@' . $this->plugin->getComponent()), '--auto-rerun=' . $input->getOption('auto-rerun'), '--verbose', '-vvv', ]; + $name = $input->getOption('name'); + if (!empty($name) && is_string($name)) { + $cmd[] = '--name=\'' . $name . '\''; + } + if ($output->isDecorated()) { $cmd[] = '--colors'; } diff --git a/tests/Command/BehatCommandTest.php b/tests/Command/BehatCommandTest.php index a971d5ea..88751df4 100644 --- a/tests/Command/BehatCommandTest.php +++ b/tests/Command/BehatCommandTest.php @@ -21,7 +21,7 @@ class BehatCommandTest extends MoodleTestCase { - protected function executeCommand($pluginDir = null, $moodleDir = null): CommandTester + protected function executeCommand($pluginDir = null, $moodleDir = null, array $cmdOptions = []): CommandTester { if ($pluginDir === null) { $pluginDir = $this->pluginDir; @@ -38,10 +38,15 @@ protected function executeCommand($pluginDir = null, $moodleDir = null): Command $application->add($command); $commandTester = new CommandTester($application->find('behat')); - $commandTester->execute([ - 'plugin' => $pluginDir, - '--moodle' => $moodleDir, - ]); + $cmdOptions = array_merge( + [ + 'plugin' => $pluginDir, + '--moodle' => $moodleDir, + ], + $cmdOptions + ); + $commandTester->execute($cmdOptions); + $this->lastCmd = $command->execute->lastCmd; // We need this for assertions against the command run. return $commandTester; } @@ -50,6 +55,28 @@ public function testExecute() { $commandTester = $this->executeCommand(); $this->assertSame(0, $commandTester->getStatusCode()); + $this->assertMatchesRegularExpression('/php.*admin.tool.behat.cli.run/', $this->lastCmd); + $this->assertMatchesRegularExpression('/--profile=default.*--suite=default/', $this->lastCmd); + $this->assertMatchesRegularExpression('/--tags=@local_ci/', $this->lastCmd); + $this->assertMatchesRegularExpression('/--verbose.*-vvv/', $this->lastCmd); + } + + public function testExecuteWithTags() + { + $commandTester = $this->executeCommand(null, null, ['--tags' => '@tag1&&@tag2']); + $this->assertSame(0, $commandTester->getStatusCode()); + $this->assertMatchesRegularExpression('/--tags=@tag1&&@tag2/', $this->lastCmd); + $this->assertDoesNotMatchRegularExpression('/--tags=@local_ci/', $this->lastCmd); + } + + public function testExecuteWithName() + { + $featureName = 'With "double quotes" and \'single quotes\''; + // Note that everything is escaped for shell execution, plus own regexp quoting. + $expectedName = preg_quote(escapeshellarg("--name='$featureName'")); + $commandTester = $this->executeCommand(null, null, ['--name' => $featureName]); + $this->assertSame(0, $commandTester->getStatusCode()); + $this->assertMatchesRegularExpression("/{$expectedName}/", $this->lastCmd); } public function testExecuteNoFeatures() @@ -70,6 +97,7 @@ public function testExecuteNoPlugin() public function testExecuteNoMoodle() { $this->expectException(\InvalidArgumentException::class); + // TODO: Check what's happening here. moodleDir should be the 2nd parameter, but then the test fails. $this->executeCommand($this->moodleDir . '/no/moodle'); } }