remove(self::$workingDir); self::$filesystem->mkdir(self::$workingDir, 0777); } /** * @AfterScenario */ public function afterScenario(): void { self::$filesystem->remove(self::$workingDir); } /** * @Given /^a Behat configuration containing(?: "([^"]+)"|:)$/ */ public function thereIsConfiguration($content): void { $mainConfigFile = sprintf('%s/behat.yml', self::$workingDir); $newConfigFile = sprintf('%s/behat-%s.yml', self::$workingDir, md5($content)); self::$filesystem->dumpFile($newConfigFile, (string) $content); if (!file_exists($mainConfigFile)) { self::$filesystem->dumpFile($mainConfigFile, Yaml::dump(['imports' => []])); } $mainBehatConfiguration = Yaml::parseFile($mainConfigFile); $mainBehatConfiguration['imports'][] = $newConfigFile; self::$filesystem->dumpFile($mainConfigFile, Yaml::dump($mainBehatConfiguration)); } /** * @Given /^a Behat configuration with the minimal working configuration for SymfonyExtension$/ */ public function thereIsConfigurationWithMinimalWorkingConfigurationForSymfonyExtension(): void { $this->thereIsConfiguration(<<<'CON' default: extensions: FriendsOfBehat\SymfonyExtension: kernel: path: app/AppKernel.php class: AppKernel CON ); } /** * @Given /^a Behat configuration with the minimal working configuration for MinkExtension$/ */ public function thereIsConfigurationWithMinimalWorkingConfigurationForMinkExtension(): void { $this->thereIsConfiguration(<<<'CON' default: extensions: Behat\MinkExtension: base_url: "http://localhost:8080/" default_session: symfony sessions: symfony: symfony: ~ CON ); } /** * @Given /^a (?:.+ |)file "([^"]+)" containing(?: "([^"]+)"|:)$/ */ public function thereIsFile($file, $content): void { self::$filesystem->dumpFile(self::$workingDir . '/' . $file, (string) $content); } /** * @Given /^an application kernel with the minimal working configuration for SymfonyExtension$/ */ public function thereIsKernelWithMinimalWorkingConfiguration(): void { $this->thereIsFile('app/AppKernel.php', <<<'CON' load(function (ContainerBuilder $container): void { $container->loadFromExtension('framework', [ 'test' => $this->getEnvironment() === 'test', 'secret' => 'Pigeon', ]); }); } } CON ); } /** * @Given /^an application kernel injecting a parameter into the FeatureContext class$/ */ public function thereIsKernelInjectingParameterIntoFeatureContextClass(): void { $this->thereIsFile('app/AppKernel.php', <<<'CON' load(function (ContainerBuilder $container): void { $container->loadFromExtension('framework', [ 'test' => $this->getEnvironment() === 'test', 'secret' => 'Pigeon', ]); $contextDefinition = new Definition(FeatureContext::class, [new Parameter('kernel.environment')]); $contextDefinition->setAutoconfigured(true); $container->setDefinition(FeatureContext::class, $contextDefinition); }); } } CON ); } /** * @Given /^a feature file containing(?: "([^"]+)"|:)$/ */ public function thereIsFeatureFile($content): void { $this->thereIsFile(sprintf('features/%s.feature', md5(uniqid('', true))), $content); } /** * @Given /^a feature file with passing scenario$/ */ public function thereIsFeatureFileWithPassingScenario(): void { $this->thereIsFile('features/bootstrap/FeatureContext.php', <<<'CON' thereIsFeatureFile(<<thereIsFile('features/bootstrap/FeatureContext.php', <<<'CON' thereIsFeatureFile(<<thereIsFile('features/bootstrap/FeatureContext.php', <<<'CON' thereIsFeatureFile(<<thereIsFile('features/bootstrap/FeatureContext.php', <<<'CON' thereIsFeatureFile(<<process = new Process(sprintf('%s %s --strict -vvv --no-interaction --lang=en', self::$phpBin, escapeshellarg(BEHAT_BIN_PATH))); $this->process->setWorkingDirectory(self::$workingDir); $this->process->start(); $this->process->wait(); } /** * @Then /^it should pass$/ */ public function itShouldPass(): void { if (0 === $this->getProcessExitCode()) { return; } throw new \DomainException( 'Behat was expecting to pass, but failed with the following output:' . PHP_EOL . PHP_EOL . $this->getProcessOutput() ); } /** * @Then /^it should pass with(?: "([^"]+)"|:)$/ */ public function itShouldPassWith($expectedOutput): void { $this->itShouldPass(); $this->assertOutputMatches((string) $expectedOutput); } /** * @Then /^it should fail$/ */ public function itShouldFail(): void { if (0 !== $this->getProcessExitCode()) { return; } throw new \DomainException( 'Behat was expecting to fail, but passed with the following output:' . PHP_EOL . PHP_EOL . $this->getProcessOutput() ); } /** * @Then /^it should fail with(?: "([^"]+)"|:)$/ */ public function itShouldFailWith($expectedOutput): void { $this->itShouldFail(); $this->assertOutputMatches((string) $expectedOutput); } /** * @Then /^it should end with(?: "([^"]+)"|:)$/ */ public function itShouldEndWith($expectedOutput): void { $this->assertOutputMatches((string) $expectedOutput); } /** * @param string $expectedOutput */ private function assertOutputMatches($expectedOutput): void { $pattern = '/' . preg_quote($expectedOutput, '/') . '/sm'; $output = $this->getProcessOutput(); $result = preg_match($pattern, $output); if (false === $result) { throw new \InvalidArgumentException('Invalid pattern given:' . $pattern); } if (0 === $result) { throw new \DomainException(sprintf( 'Pattern "%s" does not match the following output:' . PHP_EOL . PHP_EOL . '%s', $pattern, $output )); } } /** * @return string */ private function getProcessOutput(): string { $this->assertProcessIsAvailable(); return $this->process->getErrorOutput() . $this->process->getOutput(); } /** * @return int */ private function getProcessExitCode(): int { $this->assertProcessIsAvailable(); return $this->process->getExitCode(); } /** * @throws \BadMethodCallException */ private function assertProcessIsAvailable(): void { if (null === $this->process) { throw new \BadMethodCallException('Behat proccess cannot be found. Did you run it before making assertions?'); } } /** * @return string * * @throws \RuntimeException */ private static function findPhpBinary(): string { $phpBinary = (new PhpExecutableFinder())->find(); if (false === $phpBinary) { throw new \RuntimeException('Unable to find the PHP executable.'); } return $phpBinary; } }