From 19bb955db14c925d34330304913d680839ff773e Mon Sep 17 00:00:00 2001 From: Glenn McEwan Date: Wed, 31 May 2017 16:49:39 +0100 Subject: [PATCH] Update ServiceArgumentResolver to handle Symfony Container Collections (array arguments). Includes tests. --- features/bundle_suite.feature | 4 +- features/locator.feature | 2 +- .../Argument/ServiceArgumentResolverSpec.php | 13 +++++ .../Argument/ServiceArgumentResolver.php | 55 ++++++++++++++++--- testapp/app/config/config.yml | 3 + testapp/behat.yml | 2 + .../Features/Context/FeatureContext.php | 19 +++++++ .../Features/Context/WebContext.php | 2 +- .../Features/kernel_access.feature | 7 +++ 9 files changed, 95 insertions(+), 12 deletions(-) diff --git a/features/bundle_suite.feature b/features/bundle_suite.feature index ff2bbef..1aed85f 100644 --- a/features/bundle_suite.feature +++ b/features/bundle_suite.feature @@ -7,12 +7,12 @@ Feature: Bundle suites When I run "behat -s simple --no-colors" Then it should pass with: """ - 1 scenario (1 passed) + 2 scenarios (2 passed) """ Scenario: Features should be loaded from all bundle suites When I run "behat --no-colors" Then it should pass with: """ - 3 scenarios (3 passed) + 4 scenarios (4 passed) """ diff --git a/features/locator.feature b/features/locator.feature index 5e59d7f..25ded00 100644 --- a/features/locator.feature +++ b/features/locator.feature @@ -7,7 +7,7 @@ Feature: Bundle locator When I run "behat --no-colors '@BehatSf2DemoBundle'" Then it should pass with: """ - 3 scenarios (3 passed) + 4 scenarios (4 passed) """ Scenario: Specific features should be loaded from the bundle diff --git a/spec/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolverSpec.php b/spec/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolverSpec.php index 655a88e..052d5e3 100644 --- a/spec/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolverSpec.php +++ b/spec/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolverSpec.php @@ -23,12 +23,25 @@ function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they ContainerInterface $container ) { $container->getParameter('parameter')->willReturn('param_value'); + $container->hasParameter('parameter')->willReturn(true); $this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn( array('parameter' => 'param_value') ); } + function it_resolves_parameters_starting_and_ending_with_percentage_sign_if_they_point_to_parameter_collection( + ReflectionClass $reflectionClass, + ContainerInterface $container + ) { + $container->getParameter('parameter')->willReturn(array('Param 1', 'Param 2')); + $container->hasParameter('parameter')->willReturn(true); + + $this->resolveArguments($reflectionClass, array('parameter' => '%parameter%'))->shouldReturn( + array('parameter' => array('Param 1', 'Param 2')) + ); + } + function it_resolves_parameters_inside_strings( ReflectionClass $reflectionClass, ContainerInterface $container diff --git a/src/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolver.php b/src/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolver.php index 0eecc16..d594743 100644 --- a/src/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolver.php +++ b/src/Behat/Symfony2Extension/Context/Argument/ServiceArgumentResolver.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\HttpKernel\KernelInterface; /** @@ -74,9 +75,13 @@ private function resolveArgument($argument) return $service; } - $withParameters = $this->replaceParameters($container, $argument); + $resolvedParam = $this->replaceParameters($container, $argument); - return $this->escape($withParameters); + if (!is_string($resolvedParam)) { + return $resolvedParam; + } + + return $this->escape($resolvedParam); } /** @@ -108,15 +113,49 @@ private function getServiceName($argument) } /** - * @param ContainerInterface $container - * @param string $argument - * @return string + * Sanitise the container key given by the Behat config file, + * and retrieve the parameter from the Container. + * + * First, check if the whole string is one substitution, if it is, then pull it from the container. + * + * Secondly, iterate over all substitutions in the string. Exception is thrown if referencing a + * collection-type parameter when the key is not an entire substitution. + * + * This is to handle the case where we're given an argument which should return a + * collection-type parameter from the container. + * + * @param ContainerInterface $container + * @param string $argument + * @throws InvalidArgumentException + * @return mixed */ private function replaceParameters(ContainerInterface $container, $argument) { - return preg_replace_callback('/(?getParameter($matches[1]); - }, $argument); + if (preg_match('/^(?hasParameter($replaced)) { + return $container->getParameter($replaced); + } + + return $replaced; + } + + return preg_replace_callback( + '/(?getParameter($matches[1]); + + if (is_array($parameter)) { + throw new InvalidArgumentException( + 'Cannot reference a collection-type parameter with string interpolation.' + ); + } + + return $parameter; + }, + $argument + ); } /** diff --git a/testapp/app/config/config.yml b/testapp/app/config/config.yml index efcc519..c77e831 100644 --- a/testapp/app/config/config.yml +++ b/testapp/app/config/config.yml @@ -11,3 +11,6 @@ framework: parameters: custom_app: 'behat-test-app' + collection_param: + - 'Param 1' + - 'Param 2' \ No newline at end of file diff --git a/testapp/behat.yml b/testapp/behat.yml index 8ce434c..f0f2411 100644 --- a/testapp/behat.yml +++ b/testapp/behat.yml @@ -30,6 +30,8 @@ default: - "%%kernel.environment%%" - "%%kernel.debug%%" - "%%kernel.name%%" + nestedParam: 'nested_parameter_%%custom_app%%' + collectionParam: '%%collection_param%%' bundle: 'BehatSf2DemoBundle' filters: tags: '@web' diff --git a/testapp/src/Behat/Sf2DemoBundle/Features/Context/FeatureContext.php b/testapp/src/Behat/Sf2DemoBundle/Features/Context/FeatureContext.php index 1cd243f..7072c9e 100644 --- a/testapp/src/Behat/Sf2DemoBundle/Features/Context/FeatureContext.php +++ b/testapp/src/Behat/Sf2DemoBundle/Features/Context/FeatureContext.php @@ -62,4 +62,23 @@ public function itShouldBeSetToValue($val) { \PHPUnit_Framework_Assert::assertSame($val, $this->containerParameters[$this->parameterKey]); } + + /** + * @Then the value should be an array + */ + public function theValueShouldBeAnArray() + { + \PHPUnit_Framework_Assert::assertInternalType('array', $this->containerParameters[$this->parameterKey]); + } + + /** + * @Then the array should contain only the values :arg + * @param string $arg Comma delimited string, to represent an array's values + */ + public function theArrayShouldContainOnlyTheValues($arg) + { + $values = explode(',', $arg); + + \PHPUnit_Framework_Assert::assertSame($values, $this->containerParameters[$this->parameterKey]); + } } diff --git a/testapp/src/Behat/Sf2DemoBundle/Features/Context/WebContext.php b/testapp/src/Behat/Sf2DemoBundle/Features/Context/WebContext.php index 06e9bc2..38d4c68 100644 --- a/testapp/src/Behat/Sf2DemoBundle/Features/Context/WebContext.php +++ b/testapp/src/Behat/Sf2DemoBundle/Features/Context/WebContext.php @@ -11,7 +11,7 @@ class WebContext extends MinkContext implements KernelAwareContext { private $kernel; - public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params) + public function __construct(Session $session, $simpleParameter, $simpleArg, array $services, array $params, $nestedParam, $collectionParam) { } diff --git a/testapp/src/Behat/Sf2DemoBundle/Features/kernel_access.feature b/testapp/src/Behat/Sf2DemoBundle/Features/kernel_access.feature index 7b3a798..542289e 100644 --- a/testapp/src/Behat/Sf2DemoBundle/Features/kernel_access.feature +++ b/testapp/src/Behat/Sf2DemoBundle/Features/kernel_access.feature @@ -9,3 +9,10 @@ Feature: Kernel access Then there should be "custom_app" parameter And it should be set to "behat-test-app" value But there should not be "custom2" parameter + + Scenario: Allow handling of container parameters which are collections + Given I have a kernel instance + When I get container parameters from it + Then there should be "collection_param" parameter + And the value should be an array + And the array should contain only the values "Param 1,Param 2" \ No newline at end of file