From 5e8edeac9fbcb28b1783731e3c6e4cbac0e3c3d7 Mon Sep 17 00:00:00 2001 From: Veyra Hermes Agent Date: Mon, 15 Jun 2026 15:52:05 +0200 Subject: [PATCH] Add Behat 4 compatible test configuration --- behat.dist.php | 16 +++++ tests/Behat/Context/TestContext.php | 106 +++++++++++++++++++++++----- 2 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 behat.dist.php diff --git a/behat.dist.php b/behat.dist.php new file mode 100644 index 0000000..60f096d --- /dev/null +++ b/behat.dist.php @@ -0,0 +1,16 @@ +withProfile((new Profile('default')) + ->withSuite((new Suite('default')) + ->withContexts(TestContext::class), + ), + ) +; diff --git a/tests/Behat/Context/TestContext.php b/tests/Behat/Context/TestContext.php index 1a1234d..9663b5a 100644 --- a/tests/Behat/Context/TestContext.php +++ b/tests/Behat/Context/TestContext.php @@ -5,6 +5,12 @@ declare(strict_types=1); namespace Tests\Behat\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\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; @@ -28,8 +34,9 @@ final class TestContext implements Context private $variables = []; /** - * @BeforeFeature + * BeforeFeature */ + #[BeforeFeatureHook] public static function beforeFeature(): void { 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 { self::$filesystem->remove(self::$workingDir); @@ -47,16 +55,18 @@ final class TestContext implements Context } /** - * @AfterScenario + * AfterScenario */ + #[AfterScenarioHook] public function afterScenario(): void { 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 { $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 { $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 { $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 { $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 { $mainConfigFile = sprintf('%s/behat.yml', self::$workingDir); @@ -250,11 +264,64 @@ YML $mainBehatConfiguration['imports'][] = $newConfigFile; 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' + '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 { $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 { $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 { $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 { 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 { $this->itShouldPass(); @@ -324,8 +395,9 @@ YML } /** - * @Then /^it should fail$/ + * Then /^it should fail$/ */ + #[ThenStep('/^it should fail$/')] public function itShouldFail(): void { 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 { $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 { $this->assertOutputMatches((string) $expectedOutput);