diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9efe1a1..43581ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,6 +63,12 @@ jobs: run: composer test-coverage continue-on-error: ${{ vars.CI_TEST_UNIT_IGNORE_FAILURE == '1' }} + - name: Setup Chrome + uses: browser-actions/setup-chrome@v1 + + - name: Start Chrome + run: chrome --no-sandbox --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222& + - name: Run BDD tests run: composer test-bdd continue-on-error: ${{ vars.CI_TEST_BDD_IGNORE_FAILURE == '1' }} diff --git a/README.md b/README.md index 27897d9..6ddab54 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ ## Installation -```bash +```shell composer require --dev drevops/behat-screenshot ``` @@ -81,16 +81,16 @@ default: In your feature: -``` +```gherkin Given I am on "http://google.com" - Then I save screenshot +Then I save screenshot ``` You may optionally specify size of browser window in the screenshot step: -``` +```gherkin Then I save 1440 x 900 screenshot - And I save 800 x 600 screenshot +And I save 800 x 600 screenshot ``` ## Options @@ -132,28 +132,49 @@ You may optionally specify size of browser window in the screenshot step: ### Install dependencies. -```bash +```shell composer install ``` ### Lint code -```bash +```shell composer lint ``` ### Fix code style -```bash +```shell composer lint-fix ``` ### Run tests -```bash +#### Unit tests + +```shell composer test-unit # Run unit tests. +``` + +#### BDD tests + +We have tests for Selenium and Headless drivers. Selenium requires a Docker +container and headless requires a Chromium browser (we will make this more +streamlined in the future). + +```shell +# Start Chromium in container for Selenium-based tests. +docker run -d -p 4444:4444 -p 9222:9222 selenium/standalone-chromium +``` + +```shell +# Install Chromium with brew. +brew cask install chromedriver +# Launch Chromium with remote debugging. +/opt/homebrew/Caskroom/chromium/latest/chromium.wrapper.sh --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222 +``` -docker run -d -p 4444:4444 selenium/standalone-chromium +```shell composer test-bdd # Run BDD tests. BEHAT_CLI_DEBUG=1 composer test-bdd # Run BDD tests with debug output. diff --git a/composer.json b/composer.json index 9a87b3c..4271331 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "behat/mink-browserkit-driver": "^2.2", "dantleech/gherkin-lint": "^0.2.3", "dealerdirect/phpcodesniffer-composer-installer": "^1", + "dmore/behat-chrome-extension": "^1.4", "drevops/behat-phpserver": "^2.0", "drupal/coder": "^8.3", "dvdoug/behat-code-coverage": "^5.3", diff --git a/src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php b/src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php index 0c089bb..a4e2d9e 100644 --- a/src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php +++ b/src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php @@ -7,7 +7,6 @@ use Behat\Behat\Hook\Scope\AfterStepScope; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\Behat\Hook\Scope\BeforeStepScope; -use Behat\Mink\Driver\Selenium2Driver; use Behat\Mink\Exception\DriverException; use Behat\Mink\Exception\UnsupportedDriverActionException; use Behat\MinkExtension\Context\RawMinkContext; @@ -86,27 +85,26 @@ public function setScreenshotParameters(string $dir, bool $fail, string $fail_pr * @BeforeScenario */ public function beforeScenarioInit(BeforeScenarioScope $scope): void { - if ($scope->getScenario()->hasTag('javascript')) { - $driver = $this->getSession()->getDriver(); - if ($driver instanceof Selenium2Driver) { - try { - // Start driver's session manually if it is not already started. - if (!$driver->isStarted()) { - $driver->start(); - } - $this->getSession()->resizeWindow(1440, 900, 'current'); - } - catch (\Exception $exception) { - throw new \RuntimeException( - sprintf( - 'Please make sure that Selenium server is running. %s', - $exception->getMessage(), - ), - $exception->getCode(), - $exception, - ); - } + if (!$scope->getScenario()->hasTag('javascript')) { + return; + } + + $driver = $this->getSession()->getDriver(); + + try { + // Start driver's session manually if it is not already started. + if (!$driver->isStarted()) { + $driver->start(); } + + $this->getSession()->resizeWindow(1440, 900, 'current'); + } + catch (UnsupportedDriverActionException $exception) { + // Nothing to do here - drivers without support for visual screenshots + // simply do not have them created. + } + catch (DriverException $exception) { + throw new \RuntimeException(sprintf("Unable to connect to the driver's server: %s", $exception->getMessage()), $exception->getCode(), $exception); } } diff --git a/tests/behat/bootstrap/BehatCliTrait.php b/tests/behat/bootstrap/BehatCliTrait.php index 5117d04..278a1ce 100644 --- a/tests/behat/bootstrap/BehatCliTrait.php +++ b/tests/behat/bootstrap/BehatCliTrait.php @@ -182,6 +182,18 @@ public function behatCliWriteScenarioSteps(PyStringNode $content, string $tags = } } + /** + * @Given full behat configuration: + */ + public function behatCliWriteFullBehatYml(PyStringNode $content): void { + $filename = $this->workingDir . DIRECTORY_SEPARATOR . 'behat.yml'; + $this->createFile($filename, $content->getRaw()); + + if (static::behatCliIsDebug()) { + static::behatCliPrintFileContents($filename, 'Behat Config'); + } + } + /** * @Given some behat configuration */ @@ -254,7 +266,7 @@ public function behatCliWriteScreenshotFixture(): void { Test page - + Test page diff --git a/tests/behat/features/behatcli.feature b/tests/behat/features/behatcli.feature index ee92baa..656cb3f 100644 --- a/tests/behat/features/behatcli.feature +++ b/tests/behat/features/behatcli.feature @@ -56,7 +56,7 @@ Feature: Behat CLI context Test page - + Test page diff --git a/tests/behat/features/screenshot_behatcli.feature b/tests/behat/features/screenshot_behatcli.feature index e4bce7f..37f2f4d 100644 --- a/tests/behat/features/screenshot_behatcli.feature +++ b/tests/behat/features/screenshot_behatcli.feature @@ -261,7 +261,6 @@ Feature: Screenshot context # Assert that the file from the previous run is not present. And behat cli file wildcard "screenshots_custom/*.failed_stub.feature_6\.html" should not exist - @wip1 Scenario: Test Screenshot context with 'info_types' set to 'true' will output current URL to screenshot files. Given screenshot context behat configuration with value: """ @@ -297,7 +296,6 @@ Feature: Screenshot context Datetime: """ - @wip22 Scenario: Test Screenshot context with 'info_types' set to 'false' will not output current URL to screenshot files. Given screenshot context behat configuration with value: """ @@ -315,3 +313,65 @@ Feature: Screenshot context """ Current URL: http://0.0.0.0:8888/screenshot.html """ + + # Test for a headless browser using behat-chrome/behat-chrome-extension driver. + # @see https://gitlab.com/behat-chrome/behat-chrome-extension + # Install Chromium with brew: `brew cask install chromedriver` + # Launch chrome: /opt/homebrew/Caskroom/chromium/latest/chromium.wrapper.sh --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222 + @headless + Scenario: Test Screenshot context using behat-chrome/behat-chrome-extension + Given full behat configuration: + """ + default: + suites: + default: + contexts: + - FeatureContextTest: + - screenshot_dir: '%paths.base%/screenshots' + - DrevOps\BehatPhpServer\PhpServerContext: + webroot: '%paths.base%/tests/behat/fixtures' + host: 0.0.0.0 + - DrevOps\BehatScreenshotExtension\Context\ScreenshotContext + extensions: + DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ + Behat\MinkExtension: + browser_name: chrome + base_url: http://127.0.0.1:8888 + sessions: + default: + chrome: + api_url: "http://127.0.0.1:9222" + download_behavior: allow + download_path: /download + validate_certificate: false + + DrevOps\BehatScreenshotExtension: + dir: "%paths.base%/screenshots" + fail: true + purge: true + info_types: + - url + - feature + - step + - datetime + """ + And scenario steps tagged with "@phpserver": + """ + When I am on the phpserver test page + And the response status code should be 200 + And I save screenshot + """ + When I run "behat --no-colors --strict" + Then it should pass + And behat cli file wildcard "screenshots/*.stub.feature_7\.html" should exist + + And scenario steps tagged with "@phpserver": + """ + When I am on the phpserver test page + And the response status code should be 200 + # Deliberately empty line to assert for a newly created screenshot file on re-run. + And I save screenshot + """ + When I run "behat --no-colors --strict" + Then it should pass + And behat cli file wildcard "screenshots/*.stub.feature_8\.html" should exist diff --git a/tests/behat/fixtures/screenshot.html b/tests/behat/fixtures/screenshot.html index 261783e..6e06e2c 100644 --- a/tests/behat/fixtures/screenshot.html +++ b/tests/behat/fixtures/screenshot.html @@ -3,7 +3,7 @@ Test page - + Test page - \ No newline at end of file + diff --git a/tests/phpunit/Unit/ScreenshotContextTest.php b/tests/phpunit/Unit/ScreenshotContextTest.php index 06cc616..e1188a7 100644 --- a/tests/phpunit/Unit/ScreenshotContextTest.php +++ b/tests/phpunit/Unit/ScreenshotContextTest.php @@ -35,7 +35,7 @@ public function testBeforeScenarioInit(): void { ->method('hasTag')->with('javascript')->willReturn(TRUE); $session = $this->createMock(Session::class); $driver = $this->createMock(Selenium2Driver::class); - $driver->method('start')->willThrowException(new \Exception('Test Exception.')); + $driver->method('start')->willThrowException(new \RuntimeException('Test Exception.')); $session->method('getDriver')->willReturn($driver); $this->expectException(\RuntimeException::class);