Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow selenium image configuration #268

Merged
merged 1 commit into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ 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
- `--selenium` option or `MOODLE_BEHAT_SELENIUM_IMAGE` env variable to `behat` to specify Selenium Docker image.

### Changed
- Updated all uses of `actions/checkout` from `v3` (using node 16) to `v4` (using node 20), because [actions using node 16 are deprecated](https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/) and will stop working in the future.
- ACTION SUGGESTED: In order to avoid the node 16 deprecation warnings, update your workflows to use `actions/checkout@v4`.
Expand Down
14 changes: 12 additions & 2 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ Run Behat on a plugin

### Usage

* `behat [-m|--moodle MOODLE] [-p|--profile PROFILE] [--suite SUITE] [--tags TAGS] [--name NAME] [--start-servers] [--auto-rerun AUTO-RERUN] [--dump] [--] <plugin>`
* `behat [-m|--moodle MOODLE] [-p|--profile PROFILE] [--suite SUITE] [--tags TAGS] [--name NAME] [--start-servers] [--auto-rerun AUTO-RERUN] [--selenium SELENIUM] [--dump] [--] <plugin>`

Run Behat on a plugin

Expand Down Expand Up @@ -327,6 +327,16 @@ Number of times to rerun failures
* Is negatable: no
* Default: `2`

#### `--selenium`

Selenium Docker image

* Accept value: yes
* Is value required: no
* Is multiple: no
* Is negatable: no
* Default: `NULL`

#### `--dump`

Print contents of Behat failure HTML files
Expand Down Expand Up @@ -2385,4 +2395,4 @@ Do not ask any interactive question
* Is value required: no
* Is multiple: no
* Is negatable: no
* Default: `false`
* Default: `false`
47 changes: 21 additions & 26 deletions src/Command/BehatCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,6 @@ class BehatCommand extends AbstractMoodleCommand
{
use ExecuteTrait;

/**
* Selenium legacy Firefox image.
*/
private string $seleniumLegacyFirefoxImage = 'selenium/standalone-firefox:2.53.1';

/**
* Selenium standalone Firefox image.
*
* @todo: Make this configurable.
*/
private string $seleniumFirefoxImage = 'selenium/standalone-firefox:3';

/**
* Selenium standalone Chrome image.
*
* @todo: Make this configurable.
*/
private string $seleniumChromeImage = 'selenium/standalone-chrome:3';

/**
* Wait this many microseconds for Selenium server to start/stop.
*
Expand All @@ -65,6 +46,7 @@ protected function configure(): void
->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('selenium', null, InputOption::VALUE_REQUIRED, 'Selenium Docker image')
->addOption('dump', null, InputOption::VALUE_NONE, 'Print contents of Behat failure HTML files')
->setDescription('Run Behat on a plugin');
}
Expand Down Expand Up @@ -150,13 +132,7 @@ private function startServerProcesses(InputInterface $input): void
$profile = getenv('MOODLE_BEHAT_DEFAULT_BROWSER') ?: (getenv('MOODLE_APP') ? 'chrome' : 'firefox');
}

if ($profile === 'chrome') {
$image = $this->seleniumChromeImage;
} elseif ($this->usesLegacyPhpWebdriver()) {
$image = $this->seleniumLegacyFirefoxImage;
} else {
$image = $this->seleniumFirefoxImage;
}
$image = $this->getSeleniumImage($input, $profile);

$cmd = [
'docker',
Expand Down Expand Up @@ -226,4 +202,23 @@ private function usesLegacyPhpWebdriver(): bool

return strpos(file_get_contents($composerlock), 'instaclick/php-webdriver') !== false;
}

private function getSeleniumImage(InputInterface $input, string $profile): string
{
$image = $input->getOption('selenium') ?: getenv('MOODLE_BEHAT_SELENIUM_IMAGE');

if (!empty($image)) {
return $image;
}

if ($profile === 'chrome') {
return 'selenium/standalone-chrome:3';
}

if ($this->usesLegacyPhpWebdriver()) {
return 'selenium/standalone-firefox:2.53.1';
}

return 'selenium/standalone-firefox:3';
}
}
50 changes: 49 additions & 1 deletion tests/Command/BehatCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ protected function executeCommand($pluginDir = null, $moodleDir = null, array $c
$cmdOptions
);
$commandTester->execute($cmdOptions);
$this->lastCmd = $command->execute->lastCmd; // We need this for assertions against the command run.

// We need these for assertions against the commands run.
$this->allCmds = $command->execute->allCmds;
$this->lastCmd = $command->execute->lastCmd;

return $commandTester;
}
Expand All @@ -69,6 +72,51 @@ public function testExecuteWithTags()
$this->assertDoesNotMatchRegularExpression('/--tags=@local_ci/', $this->lastCmd);
}

public function testExecuteWithSeleniumImageOption()
{
$commandTester = $this->executeCommand(null, null, ['--start-servers' => true, '--selenium' => 'seleniarm/standalone-chromium:latest']);
$this->assertSame(0, $commandTester->getStatusCode());
$this->assertMatchesRegularExpression('/seleniarm\/standalone-chromium:latest/', $this->allCmds[1]);
}

public function testExecuteWithSeleniumImageEnv()
{
putenv('MOODLE_BEHAT_SELENIUM_IMAGE=seleniarm/standalone-chromium:latest');

$commandTester = $this->executeCommand(null, null, ['--start-servers' => true]);
$this->assertSame(0, $commandTester->getStatusCode());
$this->assertMatchesRegularExpression('/seleniarm\/standalone-chromium:latest/', $this->allCmds[1]);
}

public function testExecuteWithChromeProfile()
{
putenv('MOODLE_BEHAT_SELENIUM_IMAGE=');

$commandTester = $this->executeCommand(null, null, ['--start-servers' => true, '--profile' => 'chrome']);
$this->assertSame(0, $commandTester->getStatusCode());
$this->assertMatchesRegularExpression('/selenium\/standalone-chrome:3/', $this->allCmds[1]);
}

public function testExecuteWithFirefoxProfile()
{
putenv('MOODLE_BEHAT_SELENIUM_IMAGE=');
file_put_contents("{$this->moodleDir}/composer.lock", '');

$commandTester = $this->executeCommand(null, null, ['--start-servers' => true, '--profile' => 'firefox']);
$this->assertSame(0, $commandTester->getStatusCode());
$this->assertMatchesRegularExpression('/selenium\/standalone-firefox:3/', $this->allCmds[1]);
}

public function testExecuteWithLegacyFirefoxProfile()
{
putenv('MOODLE_BEHAT_SELENIUM_IMAGE=');
file_put_contents("{$this->moodleDir}/composer.lock", 'instaclick/php-webdriver');

$commandTester = $this->executeCommand(null, null, ['--start-servers' => true, '--profile' => 'firefox']);
$this->assertSame(0, $commandTester->getStatusCode());
$this->assertMatchesRegularExpression('/selenium\/standalone-firefox:2.53.1/', $this->allCmds[1]);
}

public function testExecuteWithName()
{
$featureName = 'With "double quotes" and \'single quotes\'';
Expand Down
5 changes: 4 additions & 1 deletion tests/Command/PHPUnitCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ protected function executeCommand($pluginDir = null, $moodleDir = null, array $c
$cmdOptions
);
$commandTester->execute($cmdOptions);
$this->lastCmd = $command->execute->lastCmd; // We need this for assertions against the command run.

// We need these for assertions against the commands run.
$this->allCmds = $command->execute->allCmds;
$this->lastCmd = $command->execute->lastCmd;

return $commandTester;
}
Expand Down
6 changes: 5 additions & 1 deletion tests/MoodleTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ class MoodleTestCase extends FilesystemTestCase
{
protected string $moodleDir;
protected string $pluginDir;
protected string $lastCmd = ''; // We need this for assertions against the command run.

// We need these for assertions against the commands run.
protected array $allCmds = [];
protected string $lastCmd = '';

protected function setUp(): void
{
parent::setUp();

$this->moodleDir = $this->tempDir;
$this->pluginDir = $this->tempDir . '/local/ci';
$this->allCmds = [];
$this->lastCmd = '';

$this->fs->mirror(__DIR__ . '/Fixture/moodle', $this->moodleDir);
Expand Down
Loading