76a042d670b29114005a984be58d1ea48fbda8f0
[yaffs-website] / vendor / symfony / routing / Tests / RouteCollectionBuilderTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Routing\Tests;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Config\FileLocator;
16 use Symfony\Component\Config\Resource\FileResource;
17 use Symfony\Component\Routing\Loader\YamlFileLoader;
18 use Symfony\Component\Routing\Route;
19 use Symfony\Component\Routing\RouteCollection;
20 use Symfony\Component\Routing\RouteCollectionBuilder;
21
22 class RouteCollectionBuilderTest extends TestCase
23 {
24     public function testImport()
25     {
26         $resolvedLoader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
27         $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
28         $resolver->expects($this->once())
29             ->method('resolve')
30             ->with('admin_routing.yml', 'yaml')
31             ->will($this->returnValue($resolvedLoader));
32
33         $originalRoute = new Route('/foo/path');
34         $expectedCollection = new RouteCollection();
35         $expectedCollection->add('one_test_route', $originalRoute);
36         $expectedCollection->addResource(new FileResource(__DIR__.'/Fixtures/file_resource.yml'));
37
38         $resolvedLoader
39             ->expects($this->once())
40             ->method('load')
41             ->with('admin_routing.yml', 'yaml')
42             ->will($this->returnValue($expectedCollection));
43
44         $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
45         $loader->expects($this->any())
46             ->method('getResolver')
47             ->will($this->returnValue($resolver));
48
49         // import the file!
50         $routes = new RouteCollectionBuilder($loader);
51         $importedRoutes = $routes->import('admin_routing.yml', '/', 'yaml');
52
53         // we should get back a RouteCollectionBuilder
54         $this->assertInstanceOf('Symfony\Component\Routing\RouteCollectionBuilder', $importedRoutes);
55
56         // get the collection back so we can look at it
57         $addedCollection = $importedRoutes->build();
58         $route = $addedCollection->get('one_test_route');
59         $this->assertSame($originalRoute, $route);
60         // should return file_resource.yml, which is in the original collection
61         $this->assertCount(1, $addedCollection->getResources());
62
63         // make sure the routes were imported into the top-level builder
64         $routeCollection = $routes->build();
65         $this->assertCount(1, $routes->build());
66         $this->assertCount(1, $routeCollection->getResources());
67     }
68
69     public function testImportAddResources()
70     {
71         $routeCollectionBuilder = new RouteCollectionBuilder(new YamlFileLoader(new FileLocator(array(__DIR__.'/Fixtures/'))));
72         $routeCollectionBuilder->import('file_resource.yml');
73         $routeCollection = $routeCollectionBuilder->build();
74
75         $this->assertCount(1, $routeCollection->getResources());
76     }
77
78     /**
79      * @expectedException \BadMethodCallException
80      */
81     public function testImportWithoutLoaderThrowsException()
82     {
83         $collectionBuilder = new RouteCollectionBuilder();
84         $collectionBuilder->import('routing.yml');
85     }
86
87     public function testAdd()
88     {
89         $collectionBuilder = new RouteCollectionBuilder();
90
91         $addedRoute = $collectionBuilder->add('/checkout', 'AppBundle:Order:checkout');
92         $addedRoute2 = $collectionBuilder->add('/blogs', 'AppBundle:Blog:list', 'blog_list');
93         $this->assertInstanceOf('Symfony\Component\Routing\Route', $addedRoute);
94         $this->assertEquals('AppBundle:Order:checkout', $addedRoute->getDefault('_controller'));
95
96         $finalCollection = $collectionBuilder->build();
97         $this->assertSame($addedRoute2, $finalCollection->get('blog_list'));
98     }
99
100     public function testFlushOrdering()
101     {
102         $importedCollection = new RouteCollection();
103         $importedCollection->add('imported_route1', new Route('/imported/foo1'));
104         $importedCollection->add('imported_route2', new Route('/imported/foo2'));
105
106         $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
107         // make this loader able to do the import - keeps mocking simple
108         $loader->expects($this->any())
109             ->method('supports')
110             ->will($this->returnValue(true));
111         $loader
112             ->expects($this->once())
113             ->method('load')
114             ->will($this->returnValue($importedCollection));
115
116         $routes = new RouteCollectionBuilder($loader);
117
118         // 1) Add a route
119         $routes->add('/checkout', 'AppBundle:Order:checkout', 'checkout_route');
120         // 2) Import from a file
121         $routes->mount('/', $routes->import('admin_routing.yml'));
122         // 3) Add another route
123         $routes->add('/', 'AppBundle:Default:homepage', 'homepage');
124         // 4) Add another route
125         $routes->add('/admin', 'AppBundle:Admin:dashboard', 'admin_dashboard');
126
127         // set a default value
128         $routes->setDefault('_locale', 'fr');
129
130         $actualCollection = $routes->build();
131
132         $this->assertCount(5, $actualCollection);
133         $actualRouteNames = array_keys($actualCollection->all());
134         $this->assertEquals(array(
135             'checkout_route',
136             'imported_route1',
137             'imported_route2',
138             'homepage',
139             'admin_dashboard',
140         ), $actualRouteNames);
141
142         // make sure the defaults were set
143         $checkoutRoute = $actualCollection->get('checkout_route');
144         $defaults = $checkoutRoute->getDefaults();
145         $this->assertArrayHasKey('_locale', $defaults);
146         $this->assertEquals('fr', $defaults['_locale']);
147     }
148
149     public function testFlushSetsRouteNames()
150     {
151         $collectionBuilder = new RouteCollectionBuilder();
152
153         // add a "named" route
154         $collectionBuilder->add('/admin', 'AppBundle:Admin:dashboard', 'admin_dashboard');
155         // add an unnamed route
156         $collectionBuilder->add('/blogs', 'AppBundle:Blog:list')
157             ->setMethods(array('GET'));
158
159         // integer route names are allowed - they don't confuse things
160         $collectionBuilder->add('/products', 'AppBundle:Product:list', 100);
161
162         $actualCollection = $collectionBuilder->build();
163         $actualRouteNames = array_keys($actualCollection->all());
164         $this->assertEquals(array(
165             'admin_dashboard',
166             'GET_blogs',
167             '100',
168         ), $actualRouteNames);
169     }
170
171     public function testFlushSetsDetailsOnChildrenRoutes()
172     {
173         $routes = new RouteCollectionBuilder();
174
175         $routes->add('/blogs/{page}', 'listAction', 'blog_list')
176             // unique things for the route
177             ->setDefault('page', 1)
178             ->setRequirement('id', '\d+')
179             ->setOption('expose', true)
180             // things that the collection will try to override (but won't)
181             ->setDefault('_format', 'html')
182             ->setRequirement('_format', 'json|xml')
183             ->setOption('fooBar', true)
184             ->setHost('example.com')
185             ->setCondition('request.isSecure()')
186             ->setSchemes(array('https'))
187             ->setMethods(array('POST'));
188
189         // a simple route, nothing added to it
190         $routes->add('/blogs/{id}', 'editAction', 'blog_edit');
191
192         // configure the collection itself
193         $routes
194             // things that will not override the child route
195             ->setDefault('_format', 'json')
196             ->setRequirement('_format', 'xml')
197             ->setOption('fooBar', false)
198             ->setHost('symfony.com')
199             ->setCondition('request.query.get("page")==1')
200             // some unique things that should be set on the child
201             ->setDefault('_locale', 'fr')
202             ->setRequirement('_locale', 'fr|en')
203             ->setOption('niceRoute', true)
204             ->setSchemes(array('http'))
205             ->setMethods(array('GET', 'POST'));
206
207         $collection = $routes->build();
208         $actualListRoute = $collection->get('blog_list');
209
210         $this->assertEquals(1, $actualListRoute->getDefault('page'));
211         $this->assertEquals('\d+', $actualListRoute->getRequirement('id'));
212         $this->assertTrue($actualListRoute->getOption('expose'));
213         // none of these should be overridden
214         $this->assertEquals('html', $actualListRoute->getDefault('_format'));
215         $this->assertEquals('json|xml', $actualListRoute->getRequirement('_format'));
216         $this->assertTrue($actualListRoute->getOption('fooBar'));
217         $this->assertEquals('example.com', $actualListRoute->getHost());
218         $this->assertEquals('request.isSecure()', $actualListRoute->getCondition());
219         $this->assertEquals(array('https'), $actualListRoute->getSchemes());
220         $this->assertEquals(array('POST'), $actualListRoute->getMethods());
221         // inherited from the main collection
222         $this->assertEquals('fr', $actualListRoute->getDefault('_locale'));
223         $this->assertEquals('fr|en', $actualListRoute->getRequirement('_locale'));
224         $this->assertTrue($actualListRoute->getOption('niceRoute'));
225
226         $actualEditRoute = $collection->get('blog_edit');
227         // inherited from the collection
228         $this->assertEquals('symfony.com', $actualEditRoute->getHost());
229         $this->assertEquals('request.query.get("page")==1', $actualEditRoute->getCondition());
230         $this->assertEquals(array('http'), $actualEditRoute->getSchemes());
231         $this->assertEquals(array('GET', 'POST'), $actualEditRoute->getMethods());
232     }
233
234     /**
235      * @dataProvider providePrefixTests
236      */
237     public function testFlushPrefixesPaths($collectionPrefix, $routePath, $expectedPath)
238     {
239         $routes = new RouteCollectionBuilder();
240
241         $routes->add($routePath, 'someController', 'test_route');
242
243         $outerRoutes = new RouteCollectionBuilder();
244         $outerRoutes->mount($collectionPrefix, $routes);
245
246         $collection = $outerRoutes->build();
247
248         $this->assertEquals($expectedPath, $collection->get('test_route')->getPath());
249     }
250
251     public function providePrefixTests()
252     {
253         $tests = array();
254         // empty prefix is of course ok
255         $tests[] = array('', '/foo', '/foo');
256         // normal prefix - does not matter if it's a wildcard
257         $tests[] = array('/{admin}', '/foo', '/{admin}/foo');
258         // shows that a prefix will always be given the starting slash
259         $tests[] = array('0', '/foo', '/0/foo');
260
261         // spaces are ok, and double slahses at the end are cleaned
262         $tests[] = array('/ /', '/foo', '/ /foo');
263
264         return $tests;
265     }
266
267     public function testFlushSetsPrefixedWithMultipleLevels()
268     {
269         $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
270         $routes = new RouteCollectionBuilder($loader);
271
272         $routes->add('homepage', 'MainController::homepageAction', 'homepage');
273
274         $adminRoutes = $routes->createBuilder();
275         $adminRoutes->add('/dashboard', 'AdminController::dashboardAction', 'admin_dashboard');
276
277         // embedded collection under /admin
278         $adminBlogRoutes = $routes->createBuilder();
279         $adminBlogRoutes->add('/new', 'BlogController::newAction', 'admin_blog_new');
280         // mount into admin, but before the parent collection has been mounted
281         $adminRoutes->mount('/blog', $adminBlogRoutes);
282
283         // now mount the /admin routes, above should all still be /blog/admin
284         $routes->mount('/admin', $adminRoutes);
285         // add a route after mounting
286         $adminRoutes->add('/users', 'AdminController::userAction', 'admin_users');
287
288         // add another sub-collection after the mount
289         $otherAdminRoutes = $routes->createBuilder();
290         $otherAdminRoutes->add('/sales', 'StatsController::indexAction', 'admin_stats_sales');
291         $adminRoutes->mount('/stats', $otherAdminRoutes);
292
293         // add a normal collection and see that it is also prefixed
294         $importedCollection = new RouteCollection();
295         $importedCollection->add('imported_route', new Route('/foo'));
296         // make this loader able to do the import - keeps mocking simple
297         $loader->expects($this->any())
298             ->method('supports')
299             ->will($this->returnValue(true));
300         $loader
301             ->expects($this->any())
302             ->method('load')
303             ->will($this->returnValue($importedCollection));
304         // import this from the /admin route builder
305         $adminRoutes->import('admin.yml', '/imported');
306
307         $collection = $routes->build();
308         $this->assertEquals('/admin/dashboard', $collection->get('admin_dashboard')->getPath(), 'Routes before mounting have the prefix');
309         $this->assertEquals('/admin/users', $collection->get('admin_users')->getPath(), 'Routes after mounting have the prefix');
310         $this->assertEquals('/admin/blog/new', $collection->get('admin_blog_new')->getPath(), 'Sub-collections receive prefix even if mounted before parent prefix');
311         $this->assertEquals('/admin/stats/sales', $collection->get('admin_stats_sales')->getPath(), 'Sub-collections receive prefix if mounted after parent prefix');
312         $this->assertEquals('/admin/imported/foo', $collection->get('imported_route')->getPath(), 'Normal RouteCollections are also prefixed properly');
313     }
314
315     public function testAutomaticRouteNamesDoNotConflict()
316     {
317         $routes = new RouteCollectionBuilder();
318
319         $adminRoutes = $routes->createBuilder();
320         // route 1
321         $adminRoutes->add('/dashboard', '');
322
323         $accountRoutes = $routes->createBuilder();
324         // route 2
325         $accountRoutes->add('/dashboard', '')
326             ->setMethods(array('GET'));
327         // route 3
328         $accountRoutes->add('/dashboard', '')
329             ->setMethods(array('POST'));
330
331         $routes->mount('/admin', $adminRoutes);
332         $routes->mount('/account', $accountRoutes);
333
334         $collection = $routes->build();
335         // there are 2 routes (i.e. with non-conflicting names)
336         $this->assertCount(3, $collection->all());
337     }
338
339     public function testAddsThePrefixOnlyOnceWhenLoadingMultipleCollections()
340     {
341         $firstCollection = new RouteCollection();
342         $firstCollection->add('a', new Route('/a'));
343
344         $secondCollection = new RouteCollection();
345         $secondCollection->add('b', new Route('/b'));
346
347         $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
348         $loader->expects($this->any())
349             ->method('supports')
350             ->will($this->returnValue(true));
351         $loader
352             ->expects($this->any())
353             ->method('load')
354             ->will($this->returnValue(array($firstCollection, $secondCollection)));
355
356         $routeCollectionBuilder = new RouteCollectionBuilder($loader);
357         $routeCollectionBuilder->import('/directory/recurse/*', '/other/', 'glob');
358         $routes = $routeCollectionBuilder->build()->all();
359
360         $this->assertCount(2, $routes);
361         $this->assertEquals('/other/a', $routes['a']->getPath());
362         $this->assertEquals('/other/b', $routes['b']->getPath());
363     }
364 }