Skip to content

Commit

Permalink
Remove the fork, depend on webflo/drupal-finder
Browse files Browse the repository at this point in the history
  • Loading branch information
claudiu-cristea committed Nov 16, 2022
1 parent 2541dcc commit a64a155
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 91 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"behat/mink-browserkit-driver": "^2.1.0",
"behat/mink-selenium2-driver": "~1.1",
"drupal/drupal-driver": "dev-master",
"symfony/http-client": "~4.4 || ^5 || ^6"
"symfony/http-client": "~4.4 || ^5 || ^6",
"webflo/drupal-finder": "^1.2"
},
"require-dev": {
"composer/installers": "^2",
Expand Down
88 changes: 0 additions & 88 deletions src/Drupal/DocumentElement.php

This file was deleted.

244 changes: 244 additions & 0 deletions src/Drupal/DrupalExtension/Context/ScreenshotContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
<?php

declare(strict_types = 1);

namespace Drupal\DrupalExtension\Context;

use Behat\Behat\Context\Environment\InitializedContextEnvironment;
use Behat\Behat\Hook\Scope\AfterStepScope;
use Behat\Mink\Driver\Selenium2Driver;
use Behat\Mink\Exception\DriverException;
use Behat\Mink\Exception\ExpectationException;
use Behat\MinkExtension\Context\RawMinkContext;

/**
* Provides step definitions for taking screenshots.
*
* Inspired on ScreenShotTrait from https://github.com/nuvoleweb/drupal-behat.
*
* @see https://github.com/nuvoleweb/drupal-behat
*/
class ScreenshotContext extends RawMinkContext {

/**
* Optional directory where the screenshots are saved.
*
* @var string
*/
protected $localDir;

/**
* Constructs a new ScreenshotContext context.
*
* @param string|null $localDir
* Optional directory where the screenshots are saved. If omitted the
* screenshots will not be saved.
*
* @see tests/behat.yml.dist
*/
public function __construct(?string $localDir = NULL) {
$this->localDir = $localDir;
}

/**
* Saves a screenshot under a given name.
*
* @param string|null $name
* The file name.
*
* @Then I take a screenshot :name
*/
public function takeScreenshot(?string $name = NULL): void {
$message = "Screenshot: @file_name";
$this->createScreenshots($name, $message);
}

/**
* Saves a screenshot under a predefined name.
*
* @Then I take a screenshot
*/
public function takeScreenshotUnnamed(): void {
$file_name = 'screenshot-' . \Drupal::service('password_generator')->generate();
$message = "Screenshot: @file_name";
$this->createScreenshots($file_name, $message);
}

/**
* Make sure there is no PHP notice on the screen during tests.
*
* @param \Behat\Behat\Hook\Scope\AfterStepScope $event
* The event.
*
* @AfterStep
*/
public function screenshotForPhpNotices(AfterStepScope $event): void {
$environment = $event->getEnvironment();
// Make sure the environment has the MessageContext.
$class = 'Drupal\DrupalExtension\Context\MessageContext';
if ($environment instanceof InitializedContextEnvironment && $environment->hasContextClass($class)) {
/** @var \Drupal\DrupalExtension\Context\MessageContext $context */
$context = $environment->getContext($class);
// Only check if the session is started.
try {
if ($context->getMink()->isSessionStarted()) {
try {
$context->assertNotWarningMessage('Notice:');
}
catch (ExpectationException $e) {
$message = "{$this->getStepLine($event)} screenshot: @file_name";
$this->createScreenshots($this->buildScreenshotFileName('php-notice', $event), $message, $event->getSuite()->getName());
// We don't throw $e anymore because we don't fail on the notice.
}
}
}
catch (DriverException $driver_exception) {

}
}
}

/**
* Takes a screenshot after failed steps (image or html).
*
* @param \Behat\Behat\Hook\Scope\AfterStepScope $event
* The event.
*
* @AfterStep
*/
public function takeScreenshotAfterFailedStep(AfterStepScope $event): void {
if (!$event->getTestResult()->isPassed()) {
$message = "{$this->getStepLine($event)} screenshot: @file_name";
$this->createScreenshots($this->buildScreenshotFileName('failed', $event), $message, $event->getSuite()->getName());
}
}

/**
* Creates a screenshot in HTML or PNG format.
*
* @param string $file_name
* The filename of the screenshot (complete).
* @param string $message
* The message to be printed.
* @param string|null $suite_name
* (optional) Suite name. Passed only from hook callers.
*/
protected function createScreenshots(string $file_name, string $message, ?string $suite_name = NULL): void {
try {
$screenshot = $this->getSession()->getPage()->getContent();
$this->storeScreenshot($screenshot, "{$file_name}.html", $message, $suite_name);
}
catch (DriverException $e) {
// A DriverException might occur if no page has been loaded yet so no
// screenshot can yet be taken. In this case we exit silently, allowing
// the remainder of the test suite to run.
return;
}

// For Selenium tests, create an additional .png screenshot.
if ($this->getSession()->getDriver() instanceof Selenium2Driver) {
try {
$screenshot = $this->getSession()->getDriver()->getScreenshot();
print "\n";
$this->storeScreenshot($screenshot, "{$file_name}.png", $message, $suite_name);
}
catch (DriverException $e) {
// If the .html screenshot was successful, do nothing.
}
}

// Depending on the output formatter used, Behat will suppress any output
// generated during the test. Flush the output buffers so out message will
// show up in the test logs.
ob_flush();
}

/**
* Stores the screenshot locally and, optionally, in S3.
*
* @param string $screenshot
* The screenshot content.
* @param string $file_name
* The filename of the screenshot (complete).
* @param string $message
* The message to be printed.
* @param string|null $suite_name
* (optional) Suite name. Passed only from hook callers.
*/
protected function storeScreenshot(string $screenshot, string $file_name, string $message, ?string $suite_name = NULL): void {
// Save the screenshot locally.
$path = $this->save($screenshot, $file_name, $suite_name);
print strtr($message, ['@file_name' => $path ?: $file_name]);
}

/**
* Saves the given screenshot to the local filesystem.
*
* @param string $screenshot
* The screenshot data.
* @param string $file_name
* The file name.
* @param string|null $suite_name
* (optional) If passed, will be used to build the screenshot file path.
*
* @return string|null
* The saved screenshot path.
*
* @throws \Exception
* Thrown if the destination folder doesn't exist and couldn't be created.
*/
protected function save(string $screenshot, string $file_name, ?string $suite_name = NULL): ?string {
// Don't attempt to save the screenshot if no folder name has been
// configured.
if (empty($this->localDir)) {
return NULL;
}

// Ensure the directory exists.
$dir = rtrim($this->localDir, DIRECTORY_SEPARATOR);
if ($suite_name) {
$dir .= DIRECTORY_SEPARATOR . $suite_name;
}

if (!is_dir($dir)) {
if (!mkdir($dir, 0755, TRUE)) {
throw new \Exception("The '$dir' folder does not exist and could not be created.");
}
}
$path = $dir . DIRECTORY_SEPARATOR . $file_name;
file_put_contents($path, $screenshot);

return $path;
}

/**
* Builds a filename from the feature path and failed step line.
*
* @param string $type
* The type of event (failure, PHP notice, etc).
* @param \Behat\Behat\Hook\Scope\AfterStepScope $event
* The after step event.
*
* @return string
* The screenshot filename.
*/
protected function buildScreenshotFileName(string $type, AfterStepScope $event): string {
$step_line = str_replace('/', '--', ltrim(substr($event->getFeature()->getFile(), strlen($event->getEnvironment()->getSuite()->getSetting('paths')[0])), '/'));
return "{$type}--{$step_line}--{$event->getStep()->getLine()}";
}

/**
* Returns a concatenation of the feature file name and the failed step line.
*
* @param \Behat\Behat\Hook\Scope\AfterStepScope $event
* The after step event.
*
* @return string
* A concatenation of the feature file name and the failed step line.
*/
protected function getStepLine(AfterStepScope $event): string {
// Remove the common path for readability reasons.
return ltrim(substr($event->getFeature()->getFile(), strlen($event->getEnvironment()->getSuite()->getSetting('paths')[0])), '/') . ":{$event->getStep()->getLine()}";
}

}
10 changes: 8 additions & 2 deletions src/Drupal/DrupalExtension/ServiceContainer/DrupalExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Behat\Testwork\ServiceContainer\ServiceProcessor;
use Drupal\DrupalExtension\Compiler\DriverPass;
use Drupal\DrupalExtension\Compiler\EventSubscriberPass;
use DrupalFinder\DrupalFinder;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -67,8 +68,13 @@ public function load(ContainerBuilder $container, array $config)
// of the page, pieces of texts inside the <head> section.
// @see https://github.com/minkphp/MinkBrowserKitDriver/issues/153
// @see https://www.drupal.org/project/drupal/issues/3175718
require_once(__DIR__ . '/../../DocumentElement.php');
class_alias('\Drupal\DocumentElement', '\Behat\Mink\Element\DocumentElement', true);
$drupalFinder = new DrupalFinder();
if (!$drupalFinder->locateRoot(getcwd())) {
throw new \RuntimeException('Cannot locate Drupal');
}
$drupalRoot = $drupalFinder->getDrupalRoot();
require_once($drupalRoot . '/core/tests/Drupal/Tests/DocumentElement.php');
class_alias('\Drupal\Tests\DocumentElement', '\Behat\Mink\Element\DocumentElement', true);

$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/config'));
$loader->load('services.yml');
Expand Down
28 changes: 28 additions & 0 deletions t
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -x

DRUPAL_VERSION=10
PHP_VERSION=8.1


PHP_VERSION="8.1" docker-compose down -v --remove-orphans

#sudo rm -r drupal vendor composer.lock package-lock.json node_module

PHP_VERSION="8.1" docker-compose up -d --build --force-recreate

PHP_VERSION="8.1" docker-compose exec -T -u node node npm install

PHP_VERSION="8.1" docker-compose exec -T php php -v
PHP_VERSION="8.1" docker-compose exec -T php composer self-update
PHP_VERSION="8.1" docker-compose exec -T php composer require --no-interaction --dev --no-update drupal/core:^${DRUPAL_VERSION} drupal/core-composer-scaffold:^${DRUPAL_VERSION}
PHP_VERSION="8.1" docker-compose exec -T php composer install
PHP_VERSION="8.1" docker-compose exec -T php ./vendor/bin/drush --yes --root=drupal site-install --db-url=mysql://drupal:drupal@db/drupal --debug
PHP_VERSION="8.1" docker-compose exec -T php cp -r fixtures/drupal/modules/behat_test drupal/modules
PHP_VERSION="8.1" docker-compose exec -T php ./vendor/bin/drush --yes --root=drupal pmu page_cache
PHP_VERSION="8.1" docker-compose exec -T php ./vendor/bin/drush --yes --root=drupal en behat_test
PHP_VERSION="8.1" docker-compose exec -T -u node node npm test
PHP_VERSION="8.1" docker-compose exec -T php composer test
PHP_VERSION="8.1" docker-compose exec -T php vendor/bin/behat -fprogress --strict
PHP_VERSION="8.1" docker-compose exec -T php vendor/bin/behat --profile=drupal --strict --strict

0 comments on commit a64a155

Please sign in to comment.