Add Behat 4 compatible test configuration
Some checks failed
Build / PHP 8.3 + Symfony 7.4.* (pull_request) Has been cancelled
Build / PHP 8.4 + Symfony 7.4.* (pull_request) Has been cancelled
Build / PHP 8.5 + Symfony 7.4.* (pull_request) Has been cancelled
Build / Symfony 8 + PHP 8.5 consumer install (pull_request) Has been cancelled
Build / Run Psalm (pull_request) Has been cancelled
Build / Validate composer.json (pull_request) Has been cancelled
Build / Validate Coding Standards (pull_request) Has been cancelled

This commit is contained in:
Veyra Hermes Agent
2026-06-15 15:52:05 +02:00
parent c1e8294f77
commit 5e8edeac9f
2 changed files with 106 additions and 16 deletions

16
behat.dist.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
use Behat\Config\Config;
use Behat\Config\Profile;
use Behat\Config\Suite;
use Tests\Behat\Context\TestContext;
return (new Config())
->withProfile((new Profile('default'))
->withSuite((new Suite('default'))
->withContexts(TestContext::class),
),
)
;

View File

@@ -5,6 +5,12 @@ declare(strict_types=1);
namespace Tests\Behat\Context; namespace Tests\Behat\Context;
use Behat\Behat\Context\Context; use Behat\Behat\Context\Context;
use Behat\Hook\AfterScenario as AfterScenarioHook;
use Behat\Hook\BeforeFeature as BeforeFeatureHook;
use Behat\Hook\BeforeScenario as BeforeScenarioHook;
use Behat\Step\Given as GivenStep;
use Behat\Step\Then as ThenStep;
use Behat\Step\When as WhenStep;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
@@ -28,8 +34,9 @@ final class TestContext implements Context
private $variables = []; private $variables = [];
/** /**
* @BeforeFeature * BeforeFeature
*/ */
#[BeforeFeatureHook]
public static function beforeFeature(): void public static function beforeFeature(): void
{ {
self::$workingDir = sprintf('%s/%s/', sys_get_temp_dir(), uniqid('', true)); self::$workingDir = sprintf('%s/%s/', sys_get_temp_dir(), uniqid('', true));
@@ -38,8 +45,9 @@ final class TestContext implements Context
} }
/** /**
* @BeforeScenario * BeforeScenario
*/ */
#[BeforeScenarioHook]
public function beforeScenario(): void public function beforeScenario(): void
{ {
self::$filesystem->remove(self::$workingDir); self::$filesystem->remove(self::$workingDir);
@@ -47,16 +55,18 @@ final class TestContext implements Context
} }
/** /**
* @AfterScenario * AfterScenario
*/ */
#[AfterScenarioHook]
public function afterScenario(): void public function afterScenario(): void
{ {
self::$filesystem->remove(self::$workingDir); self::$filesystem->remove(self::$workingDir);
} }
/** /**
* @Given a standard Symfony autoloader configured * Given a standard Symfony autoloader configured
*/ */
#[GivenStep('a standard Symfony autoloader configured')]
public function standardSymfonyAutoloaderConfigured(): void public function standardSymfonyAutoloaderConfigured(): void
{ {
$this->thereIsFile('vendor/autoload.php', sprintf(<<<'CON' $this->thereIsFile('vendor/autoload.php', sprintf(<<<'CON'
@@ -74,8 +84,9 @@ CON
} }
/** /**
* @Given a working Symfony application with SymfonyExtension configured * Given a working Symfony application with SymfonyExtension configured
*/ */
#[GivenStep('a working Symfony application with SymfonyExtension configured')]
public function workingSymfonyApplicationWithExtension(): void public function workingSymfonyApplicationWithExtension(): void
{ {
$this->thereIsConfiguration( $this->thereIsConfiguration(
@@ -217,24 +228,27 @@ YML
} }
/** /**
* @Given /^an? (server|environment) variable "([^"]++)" set to "([^"]++)"$/ * Given /^an? (server|environment) variable "([^"]++)" set to "([^"]++)"$/
*/ */
#[GivenStep('/^an? (server|environment) variable "([^"]++)" set to "([^"]++)"$/')]
public function variableSetTo(string $type, string $name, string $value): void public function variableSetTo(string $type, string $name, string $value): void
{ {
$this->variables[$type][$name] = $value; $this->variables[$type][$name] = $value;
} }
/** /**
* @Given /^a YAML services file containing:$/ * Given /^a YAML services file containing:$/
*/ */
#[GivenStep('/^a YAML services file containing:$/')]
public function yamlServicesFile($content): void public function yamlServicesFile($content): void
{ {
$this->thereIsFile('config/services.yaml', (string) $content); $this->thereIsFile('config/services.yaml', (string) $content);
} }
/** /**
* @Given /^a Behat configuration containing(?: "([^"]+)"|:)$/ * Given /^a Behat configuration containing(?: "([^"]+)"|:)$/
*/ */
#[GivenStep('/^a Behat configuration containing(?: "([^"]+)"|:)$/')]
public function thereIsConfiguration($content): void public function thereIsConfiguration($content): void
{ {
$mainConfigFile = sprintf('%s/behat.yml', self::$workingDir); $mainConfigFile = sprintf('%s/behat.yml', self::$workingDir);
@@ -250,11 +264,64 @@ YML
$mainBehatConfiguration['imports'][] = $newConfigFile; $mainBehatConfiguration['imports'][] = $newConfigFile;
self::$filesystem->dumpFile($mainConfigFile, Yaml::dump($mainBehatConfiguration)); self::$filesystem->dumpFile($mainConfigFile, Yaml::dump($mainBehatConfiguration));
$this->dumpPhpConfigurationBridge($mainConfigFile);
}
private function dumpPhpConfigurationBridge(string $yamlConfigFile): void
{
self::$filesystem->dumpFile(
sprintf('%s/behat.dist.php', self::$workingDir),
sprintf(
<<<'PHP'
<?php
declare(strict_types=1);
$load = static function (string $file): array {
$configuration = \Symfony\Component\Yaml\Yaml::parseFile($file);
$imports = $configuration['imports'] ?? [];
unset($configuration['imports']);
foreach ($imports as $import) {
$importedConfiguration = \Symfony\Component\Yaml\Yaml::parseFile($import);
$configuration = array_replace_recursive($configuration, $importedConfiguration);
}
$extensionClassMap = [
'FriendsOfBehat\\SymfonyExtension' => 'FriendsOfBehat\\SymfonyExtension\\ServiceContainer\\SymfonyExtension',
'Behat\\MinkExtension' => 'Behat\\MinkExtension\\ServiceContainer\\MinkExtension',
'FriendsOfBehat\\ServiceContainerExtension' => 'FriendsOfBehat\\ServiceContainerExtension\\ServiceContainer\\ServiceContainerExtension',
];
foreach ($configuration as &$profileConfiguration) {
if (!is_array($profileConfiguration['extensions'] ?? null)) {
continue;
}
foreach ($extensionClassMap as $legacyName => $className) {
if (!array_key_exists($legacyName, $profileConfiguration['extensions'])) {
continue;
}
$profileConfiguration['extensions'][$className] = $profileConfiguration['extensions'][$legacyName];
unset($profileConfiguration['extensions'][$legacyName]);
}
}
return $configuration;
};
return new \Behat\Config\Config($load(%s));
PHP
, var_export($yamlConfigFile, true),
),
);
} }
/** /**
* @Given /^a (?:.+ |)file "([^"]+)" containing(?: "([^"]+)"|:)$/ * Given /^a (?:.+ |)file "([^"]+)" containing(?: "([^"]+)"|:)$/
*/ */
#[GivenStep('/^a (?:.+ |)file "([^"]+)" containing(?: "([^"]+)"|:)$/')]
public function thereIsFile($file, $content): string public function thereIsFile($file, $content): string
{ {
$path = self::$workingDir . '/' . $file; $path = self::$workingDir . '/' . $file;
@@ -265,16 +332,18 @@ YML
} }
/** /**
* @Given /^a feature file containing(?: "([^"]+)"|:)$/ * Given /^a feature file containing(?: "([^"]+)"|:)$/
*/ */
#[GivenStep('/^a feature file containing(?: "([^"]+)"|:)$/')]
public function thereIsFeatureFile($content): void public function thereIsFeatureFile($content): void
{ {
$this->thereIsFile(sprintf('features/%s.feature', md5(uniqid('', true))), $content); $this->thereIsFile(sprintf('features/%s.feature', md5(uniqid('', true))), $content);
} }
/** /**
* @When /^I run Behat$/ * When /^I run Behat$/
*/ */
#[WhenStep('/^I run Behat$/')]
public function iRunBehat(): void public function iRunBehat(): void
{ {
$executablePath = BEHAT_BIN_PATH; $executablePath = BEHAT_BIN_PATH;
@@ -301,8 +370,9 @@ YML
} }
/** /**
* @Then /^it should pass$/ * Then /^it should pass$/
*/ */
#[ThenStep('/^it should pass$/')]
public function itShouldPass(): void public function itShouldPass(): void
{ {
if (0 === $this->getProcessExitCode()) { if (0 === $this->getProcessExitCode()) {
@@ -315,8 +385,9 @@ YML
} }
/** /**
* @Then /^it should pass with(?: "([^"]+)"|:)$/ * Then /^it should pass with(?: "([^"]+)"|:)$/
*/ */
#[ThenStep('/^it should pass with(?: "([^"]+)"|:)$/')]
public function itShouldPassWith($expectedOutput): void public function itShouldPassWith($expectedOutput): void
{ {
$this->itShouldPass(); $this->itShouldPass();
@@ -324,8 +395,9 @@ YML
} }
/** /**
* @Then /^it should fail$/ * Then /^it should fail$/
*/ */
#[ThenStep('/^it should fail$/')]
public function itShouldFail(): void public function itShouldFail(): void
{ {
if (0 !== $this->getProcessExitCode()) { if (0 !== $this->getProcessExitCode()) {
@@ -338,8 +410,9 @@ YML
} }
/** /**
* @Then /^it should fail with(?: "([^"]+)"|:)$/ * Then /^it should fail with(?: "([^"]+)"|:)$/
*/ */
#[ThenStep('/^it should fail with(?: "([^"]+)"|:)$/')]
public function itShouldFailWith($expectedOutput): void public function itShouldFailWith($expectedOutput): void
{ {
$this->itShouldFail(); $this->itShouldFail();
@@ -347,8 +420,9 @@ YML
} }
/** /**
* @Then /^it should end with(?: "([^"]+)"|:)$/ * Then /^it should end with(?: "([^"]+)"|:)$/
*/ */
#[ThenStep('/^it should end with(?: "([^"]+)"|:)$/')]
public function itShouldEndWith($expectedOutput): void public function itShouldEndWith($expectedOutput): void
{ {
$this->assertOutputMatches((string) $expectedOutput); $this->assertOutputMatches((string) $expectedOutput);