commit ef4928c2eef1ca7084ab24bbe8d61180922d9b81 Author: Kamil Kokot Date: Sat Jul 23 01:19:00 2016 +0200 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..504e6b3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/behat.yml.dist export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b747e27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/vendor + +/behat.yml +/composer.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ed6ba62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: php + +php: + - 7.0 + - 5.6 + +env: + global: + - COMPOSER_OPTIONS="" + +matrix: + include: + - + php: 5.6 + env: COMPOSER_OPTIONS="--prefer-lowest" + +cache: + directories: + - vendor + +before_install: + - phpenv config-rm xdebug.ini || true + + - composer self-update + +install: + - composer update --prefer-dist $COMPOSER_OPTIONS + +script: + - composer validate --strict + + - vendor/bin/behat --strict diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4e2960a --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 Kamil Kokot + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e53d61f --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Symfony Extension [![License](https://img.shields.io/packagist/l/friends-of-behat/symfony-extension.svg)](https://packagist.org/packages/friends-of-behat/symfony-extension) [![Version](https://img.shields.io/packagist/v/friends-of-behat/symfony-extension.svg)](https://packagist.org/packages/friends-of-behat/symfony-extension) [![Build status on Linux](https://img.shields.io/travis/FriendsOfBehat/SymfonyExtension/master.svg)](http://travis-ci.org/FriendsOfBehat/SymfonyExtension) [![Scrutinizer Quality Score](https://img.shields.io/scrutinizer/g/FriendsOfBehat/SymfonyExtension.svg)](https://scrutinizer-ci.com/g/FriendsOfBehat/SymfonyExtension/) + +Integrates Behat with Symfony (both 2 and 3). + +## Usage + +1. Install it: + +```bash +$ composer require friends-of-behat/symfony-extension --dev +``` + +2. Enable and configure in your Behat configuration: + +```yaml +default: + # ... + extensions: + FriendsOfBehat\SymfonyExtension: Z +``` + +3. Good luck & have fun! diff --git a/behat.yml.dist b/behat.yml.dist new file mode 100644 index 0000000..ccff702 --- /dev/null +++ b/behat.yml.dist @@ -0,0 +1,3 @@ +default: + extensions: + FriendsOfBehat\SymfonyExtension: ~ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..cea4ffb --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "friends-of-behat/symfony-extension", + "description": "Allows to overwrite suites' default settings.", + "license": "MIT", + "authors": [ + { + "name": "Kamil Kokot", + "email": "kamil@kokot.me", + "homepage": "http://kamil.kokot.me" + } + ], + "require": { + "php": "^5.6|^7.0", + + "behat/behat": "^3.1", + "symfony/http-kernel": "^2.7|^3.0" + }, + "require-dev": { + "behat/mink": "^1.7", + "behat/mink-browserkit-driver": "^1.3", + "behat/mink-extension": "^2.2" + }, + "autoload": { + "psr-4": { "FriendsOfBehat\\SymfonyExtension\\": "src/" } + } +} diff --git a/src/Driver/Factory/SymfonyDriverFactory.php b/src/Driver/Factory/SymfonyDriverFactory.php new file mode 100644 index 0000000..5117160 --- /dev/null +++ b/src/Driver/Factory/SymfonyDriverFactory.php @@ -0,0 +1,70 @@ + + */ +final class SymfonyDriverFactory implements DriverFactory +{ + /** + * @var string + */ + private $name; + + /** + * @var Reference + */ + private $kernel; + + /** + * @param string $name + * @param Reference $kernel + */ + public function __construct($name, Reference $kernel) + { + $this->name = $name; + $this->kernel = $kernel; + } + + /** + * {@inheritdoc} + */ + public function getDriverName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function supportsJavascript() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + + } + + /** + * {@inheritdoc} + */ + public function buildDriver(array $config) + { + return new Definition(SymfonyDriver::class, [ + $this->kernel, + '%mink.base_url%', + ]); + } +} diff --git a/src/Driver/SymfonyDriver.php b/src/Driver/SymfonyDriver.php new file mode 100644 index 0000000..fd683df --- /dev/null +++ b/src/Driver/SymfonyDriver.php @@ -0,0 +1,21 @@ + + */ +final class SymfonyDriver extends BrowserKitDriver +{ + /** + * @param KernelInterface $kernel + * @param string $baseUrl + */ + public function __construct(KernelInterface $kernel, $baseUrl) + { + parent::__construct($kernel->getContainer()->get('test.client'), $baseUrl); + } +} diff --git a/src/Listener/KernelRebooter.php b/src/Listener/KernelRebooter.php new file mode 100644 index 0000000..ffaa79a --- /dev/null +++ b/src/Listener/KernelRebooter.php @@ -0,0 +1,44 @@ + + */ +final class KernelRebooter implements EventSubscriberInterface +{ + /** + * @var KernelInterface + */ + private $kernel; + + /** + * @param KernelInterface $kernel + */ + public function __construct(KernelInterface $kernel) + { + $this->kernel = $kernel; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return [ + ScenarioTested::AFTER => ['rebootKernel', -15], + ExampleTested::AFTER => ['rebootKernel', -15], + ]; + } + + public function rebootKernel() + { + $this->kernel->shutdown(); + $this->kernel->boot(); + } +} diff --git a/src/ServiceContainer/SymfonyExtension.php b/src/ServiceContainer/SymfonyExtension.php new file mode 100644 index 0000000..f374830 --- /dev/null +++ b/src/ServiceContainer/SymfonyExtension.php @@ -0,0 +1,197 @@ + + */ +final class SymfonyExtension implements Extension +{ + /** + * Kernel used inside Behat contexts or to create services injected to them. + * Container is built before every scenario. + */ + const KERNEL_ID = 'sylius_symfony_extension.kernel'; + + /** + * The current container used in scenario contexts. + * To be used as a factory for current injected application services. + */ + const KERNEL_CONTAINER_ID = 'sylius_symfony_extension.kernel.container'; + + /** + * Kernel used by Symfony2 driver to isolate web container from contexts' container. + * Container is built before every request. + */ + const DRIVER_KERNEL_ID = 'sylius_symfony_extension.driver_kernel'; + + /** + * Kernel that should be used by extensions only. + * Container is built only once at the first use. + */ + const SHARED_KERNEL_ID = 'sylius_symfony_extension.shared_kernel'; + + /** + * The only container built by shared kernel. + * To be used as a factory for shared injected application services. + */ + const SHARED_KERNEL_CONTAINER_ID = 'sylius_symfony_extension.shared_kernel.container'; + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'fob_symfony'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + $this->registerSymfonyDriverFactory($extensionManager); + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->addDefaultsIfNotSet() + ->children() + ->arrayNode('kernel') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('bootstrap')->defaultValue('app/autoload.php')->end() + ->scalarNode('path')->defaultValue('app/AppKernel.php')->end() + ->scalarNode('class')->defaultValue('AppKernel')->end() + ->scalarNode('env')->defaultValue('test')->end() + ->booleanNode('debug')->defaultTrue()->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadKernel($container, $config['kernel']); + $this->loadKernelContainer($container); + + $this->loadDriverKernel($container); + + $this->loadSharedKernel($container); + $this->loadSharedKernelContainer($container); + + $this->loadKernelRebooter($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + + } + + /** + * @param ContainerBuilder $container + */ + private function loadKernel(ContainerBuilder $container, array $config) + { + $definition = new Definition($config['class'], array( + $config['env'], + $config['debug'], + )); + $definition->addMethodCall('boot'); + $container->setDefinition(self::KERNEL_ID, $definition); + $container->setParameter(self::KERNEL_ID . '.path', $config['path']); + $container->setParameter(self::KERNEL_ID . '.bootstrap', $config['bootstrap']); + } + + /** + * @param ContainerBuilder $container + */ + private function loadKernelContainer(ContainerBuilder $container) + { + $containerDefinition = new Definition(Container::class); + $containerDefinition->setFactory([ + new Reference(self::KERNEL_ID), + 'getContainer', + ]); + + $container->setDefinition(self::KERNEL_CONTAINER_ID, $containerDefinition); + } + + /** + * @param ContainerBuilder $container + */ + private function loadDriverKernel(ContainerBuilder $container) + { + $container->setDefinition(self::DRIVER_KERNEL_ID, $container->findDefinition(self::KERNEL_ID)); + } + + /** + * @param ContainerBuilder $container + */ + private function loadSharedKernel(ContainerBuilder $container) + { + $container->setDefinition(self::SHARED_KERNEL_ID, $container->findDefinition(self::KERNEL_ID)); + } + + /** + * @param ContainerBuilder $container + */ + private function loadSharedKernelContainer(ContainerBuilder $container) + { + $containerDefinition = new Definition(Container::class); + $containerDefinition->setFactory([ + new Reference(self::SHARED_KERNEL_ID), + 'getContainer', + ]); + + $container->setDefinition(self::SHARED_KERNEL_CONTAINER_ID, $containerDefinition); + } + + /** + * @param ContainerBuilder $container + */ + private function loadKernelRebooter(ContainerBuilder $container) + { + $definition = new Definition(KernelRebooter::class, [new Reference(self::KERNEL_ID)]); + $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG); + + $container->setDefinition(self::KERNEL_ID . '.rebooter', $definition); + } + + /** + * @param ExtensionManager $extensionManager + */ + private function registerSymfonyDriverFactory(ExtensionManager $extensionManager) + { + /** @var MinkExtension $minkExtension */ + $minkExtension = $extensionManager->getExtension('mink'); + if (null === $minkExtension) { + return; + } + + $minkExtension->registerDriverFactory(new SymfonyDriverFactory( + 'symfony', + new Reference(self::DRIVER_KERNEL_ID) + )); + } +}