├── .editorconfig ├── .formatter.yml ├── .gitignore ├── .php_cs ├── .travis.yml ├── CONTRIBUTING.md ├── Client └── SymfonyClient.php ├── Command └── GoCommand.php ├── DependencyInjection └── VisithorExtension.php ├── Environment ├── Interfaces │ └── EnvironmentBuilderInterface.php └── SymfonyEnvironmentBuilder.php ├── Generator └── SymfonyUrlGenerator.php ├── LICENSE ├── README.md ├── Resources └── config │ ├── clients.yml │ ├── commands.yml │ ├── environmentBuilders.yml │ ├── executors.yml │ ├── factories.yml │ ├── generators.yml │ └── renderers.yml ├── Tests ├── FakeBundle │ ├── Controller │ │ └── FakeController.php │ ├── DependencyInjection │ │ └── FakeExtension.php │ ├── Environment │ │ └── EnvironmentBuilder.php │ ├── FakeBundle.php │ └── Resources │ │ └── config │ │ └── environment.yml ├── Functional │ └── VisithorGoTest.php └── app │ ├── AppKernel.php │ ├── config.yml │ ├── routing.yml │ ├── security.yml │ └── visithor.yml ├── VisithorBundle.php ├── composer.json └── phpunit.xml.dist /.editorconfig: -------------------------------------------------------------------------------- 1 | ; top-most EditorConfig file 2 | root = true 3 | 4 | ; Unix-style newlines 5 | [*] 6 | end_of_line = LF 7 | 8 | [*.php] 9 | indent_style = space 10 | indent_size = 4 -------------------------------------------------------------------------------- /.formatter.yml: -------------------------------------------------------------------------------- 1 | use-sort: 2 | group: 3 | - _main 4 | - Visithor 5 | group-type: each 6 | sort-type: alph 7 | sort-direction: asc 8 | header: | 9 | /* 10 | * This file is part of the Visithor package. 11 | * 12 | * For the full copyright and license information, please view the LICENSE 13 | * file that was distributed with this source code. 14 | * 15 | * Feel free to edit as you please, and have fun. 16 | * 17 | * @author Marc Morera 18 | */ 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /bin 3 | /composer.phar 4 | /composer.lock 5 | /phpunit.xml 6 | /Tests/app/cache 7 | /Tests/app/logs 8 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | level(Symfony\CS\FixerInterface::SYMFONY_LEVEL) 6 | // and extra fixers: 7 | ->fixers(array( 8 | 'concat_with_spaces', 9 | 'multiline_spaces_before_semicolon', 10 | 'short_array_syntax', 11 | '-remove_lines_between_uses' 12 | )) 13 | ->finder( 14 | Symfony\CS\Finder\DefaultFinder::create() 15 | ->in('.') 16 | ->exclude('vendor/') 17 | ) 18 | ; 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | - hhvm 8 | - 7.0 9 | 10 | matrix: 11 | fast_finish: true 12 | 13 | install: 14 | - composer update --no-interaction --prefer-source 15 | 16 | script: 17 | - bin/phpunit 18 | 19 | notifications: 20 | email: false 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ------------ 3 | 4 | This project follows some standards. If you want to collaborate, please ensure 5 | that your code fulfills these standards before any Pull Request. 6 | 7 | ``` bash 8 | composer.phar update 9 | bin/php-cs-fixer fix 10 | bin/php-formatter formatter:use:sort src/ 11 | bin/php-formatter formatter:header:fix src/ 12 | ``` 13 | 14 | There is also a policy for contributing to this project. Pull requests must 15 | be explained step by step to make the review process easy in order to 16 | accept and merge them. New features must come paired with Unit and/or Functional 17 | tests. 18 | -------------------------------------------------------------------------------- /Client/SymfonyClient.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Client; 15 | 16 | use Exception; 17 | use Symfony\Bundle\FrameworkBundle\Client as FrameworkClient; 18 | use Symfony\Component\BrowserKit\Cookie; 19 | use Symfony\Component\HttpFoundation\Session\SessionInterface; 20 | use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; 21 | use Symfony\Component\HttpKernel\KernelInterface; 22 | use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 23 | 24 | use Visithor\Bundle\Environment\Interfaces\EnvironmentBuilderInterface; 25 | use Visithor\Client\Interfaces\ClientInterface; 26 | use Visithor\Model\Url; 27 | 28 | /** 29 | * Class SymfonyClient 30 | */ 31 | class SymfonyClient implements ClientInterface 32 | { 33 | /** 34 | * @var FrameworkClient 35 | * 36 | * Client 37 | */ 38 | protected $client; 39 | 40 | /** 41 | * @var KernelInterface 42 | * 43 | * Kernel 44 | */ 45 | protected $kernel; 46 | 47 | /** 48 | * @var SessionInterface 49 | * 50 | * Session 51 | */ 52 | protected $session; 53 | 54 | /** 55 | * @var EnvironmentBuilderInterface 56 | * 57 | * Environment Builder 58 | */ 59 | protected $environmentBuilder; 60 | 61 | /** 62 | * Construct 63 | * 64 | * @param EnvironmentBuilderInterface $environmentBuilder Environment Builder 65 | */ 66 | public function __construct( 67 | SessionInterface $session, 68 | EnvironmentBuilderInterface $environmentBuilder = null, 69 | \AppKernel $kernel = null 70 | ) { 71 | $this->session = $session; 72 | $this->environmentBuilder = $environmentBuilder; 73 | $this->kernel = $kernel; 74 | } 75 | 76 | /** 77 | * Build client 78 | * 79 | * @return $this Self object 80 | */ 81 | public function buildClient() 82 | { 83 | $this->kernel->boot(); 84 | $this->session->clear(); 85 | 86 | $this->client = $this 87 | ->kernel 88 | ->getContainer() 89 | ->get('test.client'); 90 | 91 | $this 92 | ->environmentBuilder 93 | ->setUp($this->kernel); 94 | } 95 | 96 | /** 97 | * Get the HTTP Code Response given an URL instance 98 | * 99 | * @param Url $url Url 100 | * 101 | * @return int Response HTTP Code 102 | */ 103 | public function getResponseHTTPCode(Url $url) 104 | { 105 | try { 106 | $this->authenticate($url); 107 | $verb = $url->getOption('verb', 'GET'); 108 | 109 | $this 110 | ->client 111 | ->request($verb, $url->getPath()); 112 | 113 | $result = $this 114 | ->client 115 | ->getResponse() 116 | ->getStatusCode(); 117 | } catch (AccessDeniedHttpException $e) { 118 | $result = $e->getStatusCode(); 119 | } catch (Exception $e) { 120 | $result = 'ERR'; 121 | } 122 | 123 | $this->expireAuthentication($url); 124 | 125 | return $result; 126 | } 127 | 128 | /** 129 | * Authenticates a user if is needed. 130 | * 131 | * A user is needed to be authenticated if in the url a role and a firewall 132 | * is specified. Otherwise, the system will understand that is a public url 133 | * 134 | * @param Url $url Url 135 | * 136 | * @return $this Self object 137 | */ 138 | protected function authenticate(Url $url) 139 | { 140 | if ( 141 | !$url->getOption('role') || 142 | !$url->getOption('firewall') 143 | ) { 144 | return $this; 145 | } 146 | 147 | $session = $this->session; 148 | $firewall = $url->getOption('firewall'); 149 | $role = $url->getOption('role'); 150 | $user = $this 151 | ->environmentBuilder 152 | ->getAuthenticationUser($url->getOption('role')); 153 | 154 | $token = new UsernamePasswordToken($user, null, $firewall, [$role]); 155 | $session->set('_security_' . $firewall, serialize($token)); 156 | $session->save(); 157 | 158 | $cookie = new Cookie( 159 | $session->getName(), 160 | $session->getId() 161 | ); 162 | $this 163 | ->client 164 | ->getCookieJar() 165 | ->set($cookie); 166 | 167 | return $this; 168 | } 169 | 170 | /** 171 | * Expires the authentication if these has been created 172 | * 173 | * @param Url $url Url 174 | * 175 | * @return $this Self object 176 | */ 177 | protected function expireAuthentication(Url $url) 178 | { 179 | $session = $this->session; 180 | $session->remove('_security_' . $url->getOption('firewall')); 181 | $session->save(); 182 | 183 | $this 184 | ->client 185 | ->getCookieJar() 186 | ->expire($session->getName()); 187 | 188 | return $this; 189 | } 190 | 191 | /** 192 | * Destroy client 193 | * 194 | * @return $this Self object 195 | */ 196 | public function destroyClient() 197 | { 198 | $this 199 | ->environmentBuilder 200 | ->tearDown($this->kernel); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Command/GoCommand.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Command; 15 | 16 | use Symfony\Component\Console\Output\OutputInterface; 17 | 18 | use Visithor\Command\GoCommand as OriginalGoCommand; 19 | use Visithor\Executor\Executor; 20 | use Visithor\Generator\UrlGenerator; 21 | use Visithor\Renderer\RendererFactory; 22 | 23 | /** 24 | * Class GoCommand 25 | */ 26 | class GoCommand extends OriginalGoCommand 27 | { 28 | /** 29 | * @var UrlGenerator 30 | * 31 | * URL instances generator 32 | */ 33 | protected $urlGenerator; 34 | 35 | /** 36 | * @var RendererFactory 37 | * 38 | * Renderer factory 39 | */ 40 | protected $rendererFactory; 41 | 42 | /** 43 | * @var Executor 44 | * 45 | * Visithor Executor 46 | */ 47 | protected $executor; 48 | 49 | /** 50 | * Construct 51 | * 52 | * @param UrlGenerator $urlGenerator Url generator 53 | * @param RendererFactory $rendererFactory Render factory 54 | * @param Executor $executor Executor 55 | */ 56 | public function __construct( 57 | UrlGenerator $urlGenerator, 58 | RendererFactory $rendererFactory, 59 | Executor $executor 60 | ) { 61 | parent::__construct(); 62 | 63 | $this->urlGenerator = $urlGenerator; 64 | $this->rendererFactory = $rendererFactory; 65 | $this->executor = $executor; 66 | } 67 | 68 | /** 69 | * Executes all business logic inside this command 70 | * 71 | * This method returns 0 if all executions passed. 1 otherwise. 72 | * 73 | * @param OutputInterface $output Output 74 | * @param array $config Config 75 | * @param string $format Format 76 | * 77 | * @return integer Execution return 78 | */ 79 | protected function executeVisithor( 80 | OutputInterface $output, 81 | array $config, 82 | $format 83 | ) { 84 | $renderer = $this 85 | ->rendererFactory 86 | ->create($format); 87 | 88 | $this 89 | ->executor 90 | ->build(); 91 | 92 | $urlChain = $this 93 | ->urlGenerator 94 | ->generate($config); 95 | 96 | $result = $this 97 | ->executor 98 | ->execute( 99 | $urlChain, 100 | $renderer, 101 | $output 102 | ); 103 | 104 | $this 105 | ->executor 106 | ->destroy(); 107 | 108 | return $result; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /DependencyInjection/VisithorExtension.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\DependencyInjection; 15 | 16 | use Symfony\Component\Config\FileLocator; 17 | use Symfony\Component\DependencyInjection\ContainerBuilder; 18 | use Symfony\Component\DependencyInjection\Extension\Extension; 19 | use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 20 | 21 | /** 22 | * Class VisithorExtension 23 | */ 24 | class VisithorExtension extends Extension 25 | { 26 | /** 27 | * Loads a specific configuration. 28 | * 29 | * @param array $config An array of configuration values 30 | * @param ContainerBuilder $container A ContainerBuilder instance 31 | * 32 | * @throws \InvalidArgumentException When provided tag is not defined in this extension 33 | * 34 | * @api 35 | */ 36 | public function load(array $config, ContainerBuilder $container) 37 | { 38 | $loader = new YamlFileLoader( 39 | $container, new 40 | FileLocator(__DIR__ . '/../Resources/config') 41 | ); 42 | 43 | $loader->load('clients.yml'); 44 | $loader->load('commands.yml'); 45 | $loader->load('factories.yml'); 46 | $loader->load('generators.yml'); 47 | $loader->load('executors.yml'); 48 | $loader->load('renderers.yml'); 49 | $loader->load('environmentBuilders.yml'); 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getAlias() 56 | { 57 | return 'visithor'; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Environment/Interfaces/EnvironmentBuilderInterface.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Environment\Interfaces; 15 | 16 | use Symfony\Component\HttpKernel\KernelInterface; 17 | 18 | /** 19 | * Interface EnvironmentBuilderInterface 20 | */ 21 | interface EnvironmentBuilderInterface 22 | { 23 | /** 24 | * Set up environment 25 | * 26 | * @param KernelInterface $kernel Kernel 27 | * 28 | * @return $this Self object 29 | */ 30 | public function setUp(KernelInterface $kernel); 31 | 32 | /** 33 | * Tear down environment 34 | * 35 | * @param KernelInterface $kernel Kernel 36 | * 37 | * @return $this Self object 38 | */ 39 | public function tearDown(KernelInterface $kernel); 40 | 41 | /** 42 | * Get authenticated user 43 | * 44 | * @param string $role Role 45 | * 46 | * @return mixed User for authentication 47 | */ 48 | public function getAuthenticationUser($role); 49 | } 50 | -------------------------------------------------------------------------------- /Environment/SymfonyEnvironmentBuilder.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Environment; 15 | 16 | use Symfony\Bundle\FrameworkBundle\Console\Application; 17 | use Symfony\Component\Console\Input\ArrayInput; 18 | use Symfony\Component\HttpKernel\KernelInterface; 19 | 20 | use Visithor\Bundle\Environment\Interfaces\EnvironmentBuilderInterface; 21 | 22 | /** 23 | * Class SymfonyEnvironmentBuilder 24 | */ 25 | class SymfonyEnvironmentBuilder implements EnvironmentBuilderInterface 26 | { 27 | /** 28 | * @var Application 29 | * 30 | * Application 31 | */ 32 | protected $application; 33 | 34 | /** 35 | * Set up environment 36 | * 37 | * @param KernelInterface $kernel Kernel 38 | * 39 | * @return $this Self object 40 | */ 41 | public function setUp(KernelInterface $kernel) 42 | { 43 | $this->application = new Application($kernel); 44 | $this->application->setAutoExit(false); 45 | 46 | $this 47 | ->executeCommand('doctrine:database:drop', [ 48 | '--force' => true, 49 | ]) 50 | ->executeCommand('doctrine:database:create') 51 | ->executeCommand('doctrine:schema:create'); 52 | } 53 | 54 | /** 55 | * Tear down environment 56 | * 57 | * @param KernelInterface $kernel Kernel 58 | * 59 | * @return $this Self object 60 | */ 61 | public function tearDown(KernelInterface $kernel) 62 | { 63 | $this 64 | ->executeCommand('doctrine:database:drop', [ 65 | '--force' => true, 66 | ]); 67 | } 68 | 69 | /** 70 | * Get authenticated user 71 | * 72 | * @param string $role Role 73 | * 74 | * @return mixed User for authentication 75 | */ 76 | public function getAuthenticationUser($role) 77 | { 78 | return 'admin'; 79 | } 80 | 81 | /** 82 | * Execute a command 83 | * 84 | * @param string $command Command 85 | * @param array $parameters Parameters 86 | * 87 | * @return $this Self object 88 | */ 89 | protected function executeCommand( 90 | $command, 91 | array $parameters = [] 92 | ) { 93 | $environment = $this 94 | ->application 95 | ->getKernel() 96 | ->getEnvironment(); 97 | 98 | $this 99 | ->application 100 | ->run(new ArrayInput(array_merge( 101 | [ 102 | 'command' => $command, 103 | '--no-interaction' => true, 104 | '--env' => $environment, 105 | '--quiet' => true, 106 | ], $parameters 107 | ))); 108 | 109 | return $this; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Generator/SymfonyUrlGenerator.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Generator; 15 | 16 | use Symfony\Component\Routing\Exception\ExceptionInterface; 17 | use Symfony\Component\Routing\RouterInterface; 18 | 19 | use Visithor\Factory\UrlChainFactory; 20 | use Visithor\Factory\UrlFactory; 21 | use Visithor\Generator\UrlGenerator; 22 | 23 | /** 24 | * Class SymfonyUrlGenerator 25 | */ 26 | class SymfonyUrlGenerator extends UrlGenerator 27 | { 28 | /** 29 | * @var RouterInterface 30 | * 31 | * Router 32 | */ 33 | protected $router; 34 | 35 | /** 36 | * Construct 37 | * 38 | * @param UrlFactory $urlFactory Url factory 39 | * @param UrlChainFactory $urlChainFactory UrlChain factory 40 | * @param RouterInterface $router Router 41 | */ 42 | public function __construct( 43 | UrlFactory $urlFactory, 44 | UrlChainFactory $urlChainFactory, 45 | RouterInterface $router 46 | ) { 47 | parent::__construct( 48 | $urlFactory, 49 | $urlChainFactory 50 | ); 51 | 52 | $this->router = $router; 53 | } 54 | 55 | /** 56 | * Build the url given the configuration data 57 | * 58 | * @param mixed $urlConfig Url configuration 59 | * 60 | * @return string Route path 61 | */ 62 | protected function getUrlPathFromConfig($urlConfig) 63 | { 64 | $urlPath = parent::getUrlPathFromConfig($urlConfig); 65 | 66 | try { 67 | $path = is_array($urlPath) 68 | ? $urlPath[0] 69 | : $urlPath; 70 | 71 | $arguments = ( 72 | is_array($urlPath) && 73 | isset($urlPath[1]) && 74 | is_array($urlPath[1]) 75 | ) 76 | ? $urlPath[1] 77 | : []; 78 | 79 | $urlPath = $this 80 | ->router 81 | ->generate($path, $arguments); 82 | } catch (ExceptionInterface $e) { 83 | 84 | /** 85 | * Silent pass 86 | */ 87 | } 88 | 89 | return $urlPath; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Marc Morera 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 | Visithor Bundle for Symfony 2 | =========================== 3 | 4 | [![Build Status](https://travis-ci.org/Visithor/VisithorBundle.png?branch=master)](https://travis-ci.org/Visithor/VisithorBundle) 5 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Visithor/VisithorBundle/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Visithor/VisithorBundle/?branch=master) 6 | [![Latest Stable Version](https://poser.pugx.org/visithor/visithor-bundle/v/stable.png)](https://packagist.org/packages/visithor/visithor-bundle) 7 | [![Latest Unstable Version](https://poser.pugx.org/visithor/visithor-bundle/v/unstable.png)](https://packagist.org/packages/visithor/visithor-bundle) 8 | 9 | Symfony Bundle for PHP Package [visithor](http://github.com/visithor/visithor), 10 | a library that provides you a simple and painless way of testing your 11 | application routes with specific HTTP Codes. 12 | 13 | Please read [Visithor](http://github.com/visithor/visithor) documentation in 14 | order to understand the final purpose of this project and how you should create 15 | your config files. 16 | 17 | ## Installation 18 | 19 | All you need to do is add this package in your composer under `require-dev` 20 | block and you will be able to test your application. 21 | 22 | ``` yaml 23 | 'require-dev': 24 | ... 25 | 26 | 'visithor/visithor-bundle': '~0.1' 27 | ``` 28 | 29 | Then you have to update your dependencies. 30 | 31 | ``` bash 32 | php composer.phar update 33 | ``` 34 | 35 | ## Integration 36 | 37 | This Bundle integrates the project in your Symfony project. This means that adds 38 | all the commands in your project console, so when you do `app/console` you will 39 | see the `visithor:*` commands. 40 | 41 | ``` bash 42 | php app/console visithor:go --env=test 43 | ``` 44 | 45 | ## Config 46 | 47 | This Bundle provides you some extra features when defining your urls. Now you 48 | can define your routes using the route name and an array of parameters. 49 | 50 | ``` yml 51 | defaults: 52 | # 53 | # This value can be a simple HTTP Code or an array of acceptable HTTP Codes 54 | # - 200 55 | # - [200, 301] 56 | # 57 | http_codes: [200, 302] 58 | 59 | urls: 60 | # 61 | # By default, is there is no specified HTTP Code, then default one is used 62 | # as the valid one 63 | # 64 | - http://google.es 65 | - http://elcodi.io 66 | 67 | # 68 | # There are some other formats available as well 69 | # 70 | - [http://shopery.com, 200] 71 | - [http://shopery.com, [200, 302]] 72 | 73 | # 74 | # This Bundle adds some extra formats 75 | # 76 | - [store_homepage, 200] 77 | - [[store_category_products_list, {'slug': 'women-shirts', 'id': 1}], 200] 78 | - [[store_category_products_list, {'slug': 'another-name', 'id': 1}], 302] 79 | - [[store_homepage, {_locale: es}]] 80 | ``` 81 | 82 | ## Environment 83 | 84 | Maybe you need to prepare your environment before Visithor tests your routes, 85 | right? Prepare your database, load your fixtures, and whatever you need to make 86 | your test installation works. 87 | 88 | By default, VisithorBundle has a simple implementation already working. This 89 | implementation takes care about building the database and creating your schema. 90 | 91 | ``` bash 92 | php app/console doctrine:database:create 93 | php app/console doctrine:schema:update 94 | ``` 95 | 96 | It takes care as well of the destruction of your testing database once your test 97 | is finished. 98 | 99 | ``` bash 100 | php app/console doctrine:database:drop --force 101 | ``` 102 | 103 | If you want to extend this behavior, for example for some fixtures load, then 104 | you need to do your own implementation, or extend this one. 105 | 106 | To implement your own, you should define a service called 107 | `visitor.environment_builder` than implements the interface 108 | `Visithor\Bundle\Environment\Interfaces\EnvironmentBuilderInterface`. 109 | 110 | If you take a look at this interface, you will se that you need to define two 111 | methods. The first one is intended to setUp your environment and will be called 112 | just once at the beginning of the suite. The second one will tear down such 113 | environment (for example removing database). 114 | 115 | ``` php 116 | use Symfony\Component\HttpKernel\KernelInterface; 117 | use Visithor\Bundle\Environment\Interfaces\EnvironmentBuilderInterface; 118 | 119 | /** 120 | * Class EnvironmentBuilder 121 | */ 122 | class EnvironmentBuilder implements EnvironmentBuilderInterface 123 | { 124 | /** 125 | * Set up environment 126 | * 127 | * @param KernelInterface $kernel Kernel 128 | * 129 | * @return $this Self object 130 | */ 131 | public function setUp(KernelInterface $kernel) 132 | { 133 | // 134 | } 135 | 136 | /** 137 | * Tear down environment 138 | * 139 | * @param KernelInterface $kernel Kernel 140 | * 141 | * @return $this Self object 142 | */ 143 | public function tearDown(KernelInterface $kernel) 144 | { 145 | // 146 | } 147 | 148 | /** 149 | * Get authenticated user 150 | * 151 | * @param string $role Role 152 | * 153 | * @return mixed User for authentication 154 | */ 155 | public function getAuthenticationUser($role) 156 | { 157 | // 158 | } 159 | } 160 | ``` 161 | 162 | This is the way you can overwrite completely the default implementation, but if 163 | you just want to extend it, then is much simpler. Take a look at this example. 164 | 165 | ``` php 166 | namespace Elcodi\Common\VisithorBridgeBundle\Visithor; 167 | 168 | use Doctrine\DBAL\Connection; 169 | use Symfony\Bundle\FrameworkBundle\Console\Application; 170 | use Symfony\Component\Console\Input\ArrayInput; 171 | use Symfony\Component\HttpKernel\KernelInterface; 172 | use Visithor\Bundle\Environment\SymfonyEnvironmentBuilder; 173 | 174 | /** 175 | * Class EnvironmentBuilder 176 | */ 177 | class EnvironmentBuilder extends SymfonyEnvironmentBuilder 178 | { 179 | /** 180 | * Set up environment 181 | * 182 | * @param KernelInterface $kernel Kernel 183 | * 184 | * @return $this Self object 185 | */ 186 | public function setUp(KernelInterface $kernel) 187 | { 188 | parent::setUp($kernel); 189 | 190 | $this 191 | ->executeCommand('doctrine:fixtures:load', [ 192 | '--fixtures' => $kernel 193 | ->getRootDir() . '/../src/Elcodi/Fixtures', 194 | ]) 195 | ->executeCommand('elcodi:templates:load') 196 | ->executeCommand('elcodi:templates:enable', [ 197 | 'template' => 'StoreTemplateBundle', 198 | ]) 199 | ->executeCommand('elcodi:plugins:load') 200 | ->executeCommand('assets:install') 201 | ->executeCommand('assetic:dump'); 202 | } 203 | } 204 | ``` 205 | 206 | To call some commands you can use the protected method called `executeCommand`, 207 | but remember to call the parent method in order to initialize the application 208 | and call the already existing code. 209 | 210 | ## Roles 211 | 212 | You will, for sure, have the need to test your private routes. Of course, this 213 | is a common need and this bundle satisfies it :) 214 | 215 | Let's check our simple security file. 216 | 217 | ``` yaml 218 | security: 219 | 220 | providers: 221 | in_memory: 222 | memory: ~ 223 | 224 | firewalls: 225 | default: 226 | provider: in_memory 227 | http_basic: ~ 228 | anonymous: ~ 229 | 230 | access_control: 231 | - { path: ^/admin, roles: ROLE_ADMIN } 232 | - { path: ^/superadmin, roles: ROLE_SUPERADMIN } 233 | ``` 234 | 235 | Then, let's see our Visithor configuration. 236 | 237 | ``` yaml 238 | urls: 239 | - ['/', 200] 240 | - ['/admin', 200, {'role': 'ROLE_ADMIN', 'firewall': 'default'}] 241 | - ['/superadmin', 403, {'role': 'ROLE_ADMIN', 'firewall': 'default'}] 242 | ``` 243 | 244 | In this case, all routes are under the default firewall, called `default`. 245 | 246 | Route `admin_route` is protected by the access role `ROLE_ADMIN`, and because we 247 | are testing against this role, then we'll receive a 200. 248 | 249 | Route `superadmin_route` is protected by the access role `ROLE_SUPERADMIN`, but 250 | in this case we are testing again using role `ROLE_ADMIN`, so we'll receive a 251 | 403 code. 252 | 253 | Of course, you can define your firewall as a global option. Your routes will 254 | apply security only if both role and firewall options are defined. 255 | 256 | ``` yaml 257 | defaults: 258 | options: 259 | firewall: default 260 | urls: 261 | - ['/', 200] 262 | - ['/admin', 200, {'role': 'ROLE_ADMIN'}] 263 | - ['/superadmin', 403, {'role': 'ROLE_ADMIN'}] 264 | ``` 265 | 266 | Because you need to authenticate a real user in order to make it work, in your 267 | own EnvironmentBuilder implementation you will be able to return this user. Make 268 | sure that your testing environment is prepared to be tested. 269 | 270 | Let's see a real example about an implementation of this method. 271 | 272 | ``` php 273 | /** 274 | * Get authenticated user 275 | * 276 | * @param string $role Role 277 | * 278 | * @return mixed User for authentication 279 | */ 280 | public function getAuthenticationUser($role) 281 | { 282 | return 'ROLE_ADMIN' === $role 283 | ? $this 284 | ->adminUserRepository 285 | ->findOneBy([ 286 | 'email' => 'admin@admin.com' 287 | ]) 288 | : null; 289 | } 290 | ``` 291 | 292 | As you can see, the parameter received is the role you are intended to test, so 293 | you can switch between users depending on that value. 294 | -------------------------------------------------------------------------------- /Resources/config/clients.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Clients 5 | # 6 | visithor.client: 7 | class: Visithor\Bundle\Client\SymfonyClient 8 | arguments: 9 | - "@session" 10 | - "@visitor.environment_builder" 11 | - "@visithor.client.app_kernel" 12 | 13 | visithor.client.app_kernel: 14 | public: false 15 | class: AppKernel 16 | arguments: 17 | - "%kernel.environment%" 18 | - "%kernel.debug%" 19 | -------------------------------------------------------------------------------- /Resources/config/commands.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Commands 5 | # 6 | visithor.command.go: 7 | class: Visithor\Bundle\Command\GoCommand 8 | arguments: 9 | - "@visithor.url_generator" 10 | - "@visithor.renderer_factory" 11 | - "@visithor.executor" 12 | tags: 13 | - { name: console.command } 14 | -------------------------------------------------------------------------------- /Resources/config/environmentBuilders.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Environment Builders 5 | # 6 | visitor.environment_builder: 7 | class: Visithor\Bundle\Environment\SymfonyEnvironmentBuilder 8 | -------------------------------------------------------------------------------- /Resources/config/executors.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Executors 5 | # 6 | visithor.executor: 7 | class: Visithor\Executor\Executor 8 | lazy: true 9 | arguments: 10 | - "@visithor.client" 11 | -------------------------------------------------------------------------------- /Resources/config/factories.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Factories 5 | # 6 | visithor.factory.url: 7 | class: Visithor\Factory\UrlFactory 8 | 9 | visithor.factory.url_chain: 10 | class: Visithor\Factory\UrlChainFactory 11 | -------------------------------------------------------------------------------- /Resources/config/generators.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Generators 5 | # 6 | visithor.url_generator: 7 | class: Visithor\Bundle\Generator\SymfonyUrlGenerator 8 | arguments: 9 | - "@visithor.factory.url" 10 | - "@visithor.factory.url_chain" 11 | - "@router" 12 | -------------------------------------------------------------------------------- /Resources/config/renderers.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Renderers 5 | # 6 | visithor.renderer_factory: 7 | class: Visithor\Renderer\RendererFactory 8 | -------------------------------------------------------------------------------- /Tests/FakeBundle/Controller/FakeController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Tests\FakeBundle\Controller; 15 | 16 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; 17 | use Symfony\Component\HttpFoundation\Response; 18 | 19 | /** 20 | * Fake Controller object 21 | */ 22 | class FakeController extends Controller 23 | { 24 | /** 25 | * Default method 26 | */ 27 | public function defaultAction() 28 | { 29 | return new Response('', 200); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/FakeBundle/DependencyInjection/FakeExtension.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Tests\FakeBundle\DependencyInjection; 15 | 16 | use Symfony\Component\Config\FileLocator; 17 | use Symfony\Component\DependencyInjection\ContainerBuilder; 18 | use Symfony\Component\DependencyInjection\Extension\Extension; 19 | use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 20 | 21 | /** 22 | * Class FakeExtension 23 | */ 24 | class FakeExtension extends Extension 25 | { 26 | /** 27 | * Loads a specific configuration. 28 | * 29 | * @param array $config An array of configuration values 30 | * @param ContainerBuilder $container A ContainerBuilder instance 31 | * 32 | * @throws \InvalidArgumentException When provided tag is not defined in this extension 33 | * 34 | * @api 35 | */ 36 | public function load(array $config, ContainerBuilder $container) 37 | { 38 | $loader = new YamlFileLoader( 39 | $container, new 40 | FileLocator(__DIR__ . '/../Resources/config') 41 | ); 42 | 43 | $loader->load('environment.yml'); 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getAlias() 50 | { 51 | return 'fake'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Tests/FakeBundle/Environment/EnvironmentBuilder.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Tests\FakeBundle\Environment; 15 | 16 | use Symfony\Component\HttpKernel\KernelInterface; 17 | 18 | use Visithor\Bundle\Environment\Interfaces\EnvironmentBuilderInterface; 19 | 20 | /** 21 | * Class EnvironmentBuilder 22 | */ 23 | class EnvironmentBuilder implements EnvironmentBuilderInterface 24 | { 25 | /** 26 | * Set up environment 27 | * 28 | * @param KernelInterface $kernel Kernel 29 | * 30 | * @return $this Self object 31 | */ 32 | public function setUp(KernelInterface $kernel) 33 | { 34 | return $this; 35 | } 36 | 37 | /** 38 | * Tear down environment 39 | * 40 | * @param KernelInterface $kernel Kernel 41 | * 42 | * @return $this Self object 43 | */ 44 | public function tearDown(KernelInterface $kernel) 45 | { 46 | return $this; 47 | } 48 | 49 | /** 50 | * Get authenticated user 51 | * 52 | * @param string $role Role 53 | * 54 | * @return mixed User for authentication 55 | */ 56 | public function getAuthenticationUser($role) 57 | { 58 | return 'admin'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Tests/FakeBundle/FakeBundle.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Tests\FakeBundle; 15 | 16 | use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 17 | use Symfony\Component\HttpKernel\Bundle\Bundle; 18 | 19 | use Visithor\Bundle\Tests\FakeBundle\DependencyInjection\FakeExtension; 20 | 21 | /** 22 | * Class FakeBundle 23 | */ 24 | class FakeBundle extends Bundle 25 | { 26 | /** 27 | * Returns the bundle's container extension. 28 | * 29 | * @return ExtensionInterface The container extension 30 | */ 31 | public function getContainerExtension() 32 | { 33 | return new FakeExtension(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Tests/FakeBundle/Resources/config/environment.yml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | # 4 | # Visithor Bridge 5 | # 6 | visitor.environment_builder: 7 | class: Visithor\Bundle\Tests\FakeBundle\Environment\EnvironmentBuilder 8 | -------------------------------------------------------------------------------- /Tests/Functional/VisithorGoTest.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle\Tests\Functional; 15 | 16 | use Symfony\Bundle\FrameworkBundle\Console\Application; 17 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; 18 | use Symfony\Component\Console\Input\ArrayInput; 19 | use Symfony\Component\HttpKernel\Client; 20 | 21 | /** 22 | * Class VisithorGoTest 23 | */ 24 | class VisithorGoTest extends WebTestCase 25 | { 26 | /** 27 | * @var Client 28 | * 29 | * client 30 | */ 31 | protected $client; 32 | 33 | /** 34 | * @var Application 35 | * 36 | * application 37 | */ 38 | protected static $application; 39 | 40 | /** 41 | * Setup 42 | */ 43 | public function setUp() 44 | { 45 | static::$kernel = static::createKernel(); 46 | static::$kernel->boot(); 47 | static::$application = new Application(static::$kernel); 48 | static::$application->setAutoExit(false); 49 | $this->client = static::createClient(); 50 | } 51 | 52 | /** 53 | * Test visithor:go 54 | */ 55 | public function testVisithorGo() 56 | { 57 | $result = static::$application->run(new ArrayInput([ 58 | 'command' => 'visithor:go', 59 | '--config' => static::$kernel->getRootDir(), 60 | ])); 61 | 62 | $this->assertEquals( 63 | 0, 64 | $result 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Tests/app/AppKernel.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | use Symfony\Component\Config\Loader\LoaderInterface; 15 | use Symfony\Component\HttpKernel\Kernel; 16 | 17 | /** 18 | * AppKernel for testing 19 | */ 20 | class AppKernel extends Kernel 21 | { 22 | /** 23 | * Registers all needed bundles 24 | */ 25 | public function registerBundles() 26 | { 27 | return [ 28 | new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), 29 | new Symfony\Bundle\SecurityBundle\SecurityBundle(), 30 | new Visithor\Bundle\VisithorBundle(), 31 | new Visithor\Bundle\Tests\FakeBundle\FakeBundle(), 32 | ]; 33 | } 34 | 35 | /** 36 | * Setup configuration file. 37 | */ 38 | public function registerContainerConfiguration(LoaderInterface $loader) 39 | { 40 | $loader->load(dirname(__FILE__) . '/config.yml'); 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | * 46 | * @api 47 | */ 48 | public function getEnvironment() 49 | { 50 | return 'test'; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @api 57 | */ 58 | public function isDebug() 59 | { 60 | return false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Tests/app/config.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: security.yml } 3 | 4 | framework: 5 | test: ~ 6 | secret: fhklsdhkj 7 | form: 8 | enabled: false 9 | session: 10 | storage_id: session.storage.mock_file 11 | profiler: 12 | collect: false 13 | router: 14 | resource: "%kernel.root_dir%/routing.yml" 15 | strict_requirements: ~ 16 | -------------------------------------------------------------------------------- /Tests/app/routing.yml: -------------------------------------------------------------------------------- 1 | public_route: 2 | path: /public 3 | defaults: { _controller: FakeBundle:Fake:default } 4 | 5 | admin_route: 6 | path: /admin 7 | defaults: { _controller: FakeBundle:Fake:default } 8 | 9 | superadmin_route: 10 | path: /superadmin 11 | defaults: { _controller: FakeBundle:Fake:default } 12 | -------------------------------------------------------------------------------- /Tests/app/security.yml: -------------------------------------------------------------------------------- 1 | security: 2 | 3 | providers: 4 | in_memory: 5 | memory: 6 | users: 7 | admin: 8 | password: 1234 9 | roles: 'ROLE_ADMIN' 10 | 11 | firewalls: 12 | default: 13 | provider: in_memory 14 | http_basic: ~ 15 | anonymous: ~ 16 | 17 | access_control: 18 | - { path: ^/admin, roles: ROLE_ADMIN } 19 | - { path: ^/superadmin, roles: ROLE_SUPERADMIN } 20 | -------------------------------------------------------------------------------- /Tests/app/visithor.yml: -------------------------------------------------------------------------------- 1 | defaults: 2 | options: 3 | firewall: 'default' 4 | 5 | profiles: 6 | admin: 7 | role: ROLE_ADMIN 8 | firewall: 'default' 9 | 10 | urls: 11 | - ['/public', 200] 12 | - ['public_route', 200] 13 | - ['admin_route', 200, {'role': 'ROLE_ADMIN'}] 14 | - ['/admin', 200, {'role': 'ROLE_ADMIN'}] 15 | - ['admin_route', 200, {'role': 'ROLE_ADMIN', 'firewall': 'default'}] 16 | - ['admin_route', 200, {'profile': 'admin'}] 17 | - ['admin_route', 403, {'role': 'ROLE_ANOTHER', 'firewall': 'default'}] 18 | - ['admin_route', 401, {'firewall': 'default'}] 19 | - ['superadmin_route', 403, {'role': 'ROLE_ADMIN', 'firewall': 'default'}] 20 | - ['superadmin_route', 401, {'role': 'ROLE_ADMIN', 'firewall': 'nonexists'}] 21 | -------------------------------------------------------------------------------- /VisithorBundle.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | 14 | namespace Visithor\Bundle; 15 | 16 | use Symfony\Component\Console\Application; 17 | use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 18 | use Symfony\Component\HttpKernel\Bundle\Bundle; 19 | 20 | use Visithor\Bundle\DependencyInjection\VisithorExtension; 21 | 22 | /** 23 | * Class VisithorBundle 24 | */ 25 | class VisithorBundle extends Bundle 26 | { 27 | /** 28 | * Returns the bundle's container extension. 29 | * 30 | * @return ExtensionInterface The container extension 31 | */ 32 | public function getContainerExtension() 33 | { 34 | return new VisithorExtension(); 35 | } 36 | 37 | /** 38 | * Finds and registers Commands. 39 | * 40 | * Override this method if your bundle commands do not follow the conventions: 41 | * 42 | * * Commands are in the 'Command' sub-directory 43 | * * Commands extend Symfony\Component\Console\Command\Command 44 | * 45 | * @param Application $application An Application instance 46 | */ 47 | public function registerCommands(Application $application) 48 | { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visithor/visithor-bundle", 3 | "description": "Visithor Bundle for Symfony", 4 | "keywords": ["visithor", "php", "Symfony", "Ping"], 5 | "type": "symfony-bundle", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Marc Morera", 10 | "email": "yuhu@mmoreram.com" 11 | } 12 | ], 13 | "require": { 14 | "php": "^5.4|^7.0", 15 | "symfony/config": "^2.7|^3.0", 16 | "symfony/dependency-injection": "^2.7|^3.0", 17 | "symfony/console": "^2.7|^3.0", 18 | "symfony/routing": "^2.7|^3.0", 19 | "symfony/http-foundation": "^2.7|^3.0", 20 | "symfony/security": "^2.7|^3.0", 21 | "symfony/framework-bundle": "^2.7|^3.0", 22 | 23 | "visithor/visithor": "^0.2.0" 24 | }, 25 | "require-dev": { 26 | "symfony/security-bundle": "^2.3|^3.0", 27 | "symfony/browser-kit": "^2.3|^3.0", 28 | 29 | "fabpot/php-cs-fixer": "1.11", 30 | "mmoreram/php-formatter": "1.1.0", 31 | "phpunit/phpunit": "4.8.19" 32 | }, 33 | "config": { 34 | "bin-dir": "bin" 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "Visithor\\Bundle\\": "" 39 | } 40 | }, 41 | "extra": { 42 | "branch-alias": { 43 | "dev-master": "0.1-dev" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ./Tests/ 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------