├── .github └── workflows │ └── build.yml ├── LICENSE ├── README.md ├── composer.json └── src ├── Argument └── VariadicArgumentOrganiser.php └── ServiceContainer └── VariadicExtension.php /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: ~ 5 | pull_request: ~ 6 | release: 7 | types: [created] 8 | schedule: 9 | - 10 | cron: "0 1 * * 6" # Run at 1am every Saturday 11 | 12 | jobs: 13 | tests: 14 | runs-on: ubuntu-20.04 15 | name: "PHP ${{ matrix.php }}, Symfony ${{ matrix.symfony }}" 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | php: ["8.1", "8.2", "8.3"] 20 | symfony: ["^5.4", "^6.4", "7.0"] 21 | exclude: 22 | - php: "8.1" 23 | symfony: "7.0" 24 | 25 | steps: 26 | - uses: actions/checkout@v2 27 | 28 | - name: Setup PHP 29 | uses: shivammathur/setup-php@v2 30 | with: 31 | php-version: "${{ matrix.php }}" 32 | coverage: none 33 | 34 | - name: Restrict Symfony version 35 | if: matrix.symfony != '' 36 | run: | 37 | composer global config --no-plugins allow-plugins.symfony/flex true 38 | composer global require --no-progress --no-scripts --no-plugins "symfony/flex:^1.11" 39 | composer config extra.symfony.require "${{ matrix.symfony }}" 40 | 41 | - name: Install dependencies 42 | run: composer update 43 | 44 | - name: Run analysis 45 | run: composer validate --strict 46 | 47 | - name: Run tests 48 | run: vendor/bin/behat --strict -vvv --no-interaction 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2021 Łukasz Chruściel 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Variadic Extension [![License](https://img.shields.io/packagist/l/friends-of-behat/variadic-extension.svg)](https://packagist.org/packages/friends-of-behat/variadic-extension) [![Version](https://img.shields.io/packagist/v/friends-of-behat/variadic-extension.svg)](https://packagist.org/packages/friends-of-behat/variadic-extension) [![Build](https://github.com/FriendsOfBehat/VariadicExtension/actions/workflows/build.yml/badge.svg)](https://github.com/FriendsOfBehat/VariadicExtension/actions/workflows/build.yml) [![Scrutinizer Quality Score](https://img.shields.io/scrutinizer/g/FriendsOfBehat/VariadicExtension.svg)](https://scrutinizer-ci.com/g/FriendsOfBehat/VariadicExtension/) 2 | 3 | Adds variadic arguments support to Behat steps definitions. 4 | 5 | ## Usage 6 | 7 | 1. Install it: 8 | 9 | ```bash 10 | $ composer require friends-of-behat/variadic-extension --dev 11 | ``` 12 | 13 | 2. Enable it in your Behat configuration: 14 | 15 | ```yaml 16 | # behat.yml 17 | default: 18 | # ... 19 | extensions: 20 | FriendsOfBehat\VariadicExtension: ~ 21 | ``` 22 | 23 | 3. You can use variadic arguments in steps definitions! 24 | 25 | ```php 26 | /** 27 | * @Given the store has( also) :firstProductName and :secondProductName products 28 | * @Given the store has( also) :firstProductName, :secondProductName and :thirdProductName products 29 | * @Given the store has( also) :firstProductName, :secondProductName, :thirdProductName and :fourthProductName products 30 | */ 31 | public function theStoreHasProducts(...$productsNames) 32 | { 33 | foreach ($productsNames as $productName) { 34 | $this->saveProduct($this->createProduct($productName)); 35 | } 36 | } 37 | 38 | /** 39 | * @Given /^(this channel) has "([^"]+)", "([^"]+)", "([^"]+)" and "([^"]+)" products$/ 40 | */ 41 | public function thisChannelHasProducts(ChannelInterface $channel, ...$productsNames) 42 | { 43 | foreach ($productsNames as $productName) { 44 | $product = $this->createProduct($productName, 0, $channel); 45 | 46 | $this->saveProduct($product); 47 | } 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "friends-of-behat/variadic-extension", 3 | "description": "Variadic support for behat context arguments", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Łukasz Chruściel", 8 | "email": "lchrusciel@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": "^8.1", 13 | "behat/behat": "^3.8", 14 | "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0" 15 | }, 16 | "require-dev": { 17 | "friends-of-behat/test-context": "^1.0" 18 | }, 19 | "extra": { 20 | "branch-alias": { 21 | "dev-master": "1.5-dev" 22 | } 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "FriendsOfBehat\\VariadicExtension\\": "src/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Argument/VariadicArgumentOrganiser.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace FriendsOfBehat\VariadicExtension\Argument; 15 | 16 | use Behat\Testwork\Argument\ArgumentOrganiser; 17 | use ReflectionFunctionAbstract; 18 | 19 | /** 20 | * Decorates a default argument organiser to support a variadic arguments also. 21 | * It will add all unused arguments to the end of argument list. 22 | */ 23 | final class VariadicArgumentOrganiser implements ArgumentOrganiser 24 | { 25 | /** 26 | * @var ArgumentOrganiser 27 | */ 28 | private $decoratedArgumentOrganiser; 29 | 30 | /** 31 | * @param ArgumentOrganiser $decoratedArgumentOrganiser 32 | */ 33 | public function __construct(ArgumentOrganiser $decoratedArgumentOrganiser) 34 | { 35 | $this->decoratedArgumentOrganiser = $decoratedArgumentOrganiser; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function organiseArguments(ReflectionFunctionAbstract $function, array $arguments): array 42 | { 43 | $organisedArguments = $this->decoratedArgumentOrganiser->organiseArguments($function, $arguments); 44 | 45 | if ($function->isVariadic()) { 46 | $organisedArguments += array_diff($arguments, $organisedArguments); 47 | } 48 | 49 | return $organisedArguments; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ServiceContainer/VariadicExtension.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | 14 | namespace FriendsOfBehat\VariadicExtension\ServiceContainer; 15 | 16 | use Behat\Testwork\Argument\ServiceContainer\ArgumentExtension; 17 | use Behat\Testwork\ServiceContainer\Extension; 18 | use Behat\Testwork\ServiceContainer\ExtensionManager; 19 | use FriendsOfBehat\VariadicExtension\Argument\VariadicArgumentOrganiser; 20 | use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; 21 | use Symfony\Component\DependencyInjection\ContainerBuilder; 22 | use Symfony\Component\DependencyInjection\Definition; 23 | use Symfony\Component\DependencyInjection\Reference; 24 | 25 | final class VariadicExtension implements Extension 26 | { 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | public function getConfigKey(): string 31 | { 32 | return 'fob_variadic'; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function initialize(ExtensionManager $extensionManager): void 39 | { 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function configure(ArrayNodeDefinition $builder): void 46 | { 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function load(ContainerBuilder $container, array $config): void 53 | { 54 | $definition = new Definition(VariadicArgumentOrganiser::class, [ 55 | new Reference('fob_variadic.argument.mixed_organiser.inner'), 56 | ]); 57 | $definition->setDecoratedService(ArgumentExtension::MIXED_ARGUMENT_ORGANISER_ID); 58 | 59 | $container->setDefinition('fob_variadic.argument.mixed_organiser', $definition); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | public function process(ContainerBuilder $container): void 66 | { 67 | } 68 | } 69 | --------------------------------------------------------------------------------