From ef4928c2eef1ca7084ab24bbe8d61180922d9b81 Mon Sep 17 00:00:00 2001 From: Kamil Kokot Date: Sat, 23 Jul 2016 01:19:00 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 4 + .gitignore | 4 + .travis.yml | 32 ++++ LICENSE | 19 ++ README.md | 22 +++ behat.yml.dist | 3 + composer.json | 26 +++ src/Driver/Factory/SymfonyDriverFactory.php | 70 +++++++ src/Driver/SymfonyDriver.php | 21 +++ src/Listener/KernelRebooter.php | 44 +++++ src/ServiceContainer/SymfonyExtension.php | 197 ++++++++++++++++++++ 11 files changed, 442 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 behat.yml.dist create mode 100644 composer.json create mode 100644 src/Driver/Factory/SymfonyDriverFactory.php create mode 100644 src/Driver/SymfonyDriver.php create mode 100644 src/Listener/KernelRebooter.php create mode 100644 src/ServiceContainer/SymfonyExtension.php 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) + )); + } +}