1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Routing\Tests;
13:
14: use PHPUnit\Framework\TestCase;
15: use Symfony\Component\Routing\RouteCollection;
16: use Symfony\Component\Routing\Route;
17: use Symfony\Component\Config\Resource\FileResource;
18:
19: class RouteCollectionTest extends TestCase
20: {
21: public function testRoute()
22: {
23: $collection = new RouteCollection();
24: $route = new Route('/foo');
25: $collection->add('foo', $route);
26: $this->assertEquals(array('foo' => $route), $collection->all(), '->add() adds a route');
27: $this->assertEquals($route, $collection->get('foo'), '->get() returns a route by name');
28: $this->assertNull($collection->get('bar'), '->get() returns null if a route does not exist');
29: }
30:
31: public function testOverriddenRoute()
32: {
33: $collection = new RouteCollection();
34: $collection->add('foo', new Route('/foo'));
35: $collection->add('foo', new Route('/foo1'));
36:
37: $this->assertEquals('/foo1', $collection->get('foo')->getPath());
38: }
39:
40: public function testDeepOverriddenRoute()
41: {
42: $collection = new RouteCollection();
43: $collection->add('foo', new Route('/foo'));
44:
45: $collection1 = new RouteCollection();
46: $collection1->add('foo', new Route('/foo1'));
47:
48: $collection2 = new RouteCollection();
49: $collection2->add('foo', new Route('/foo2'));
50:
51: $collection1->addCollection($collection2);
52: $collection->addCollection($collection1);
53:
54: $this->assertEquals('/foo2', $collection1->get('foo')->getPath());
55: $this->assertEquals('/foo2', $collection->get('foo')->getPath());
56: }
57:
58: public function testIterator()
59: {
60: $collection = new RouteCollection();
61: $collection->add('foo', new Route('/foo'));
62:
63: $collection1 = new RouteCollection();
64: $collection1->add('bar', $bar = new Route('/bar'));
65: $collection1->add('foo', $foo = new Route('/foo-new'));
66: $collection->addCollection($collection1);
67: $collection->add('last', $last = new Route('/last'));
68:
69: $this->assertInstanceOf('\ArrayIterator', $collection->getIterator());
70: $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'last' => $last), $collection->getIterator()->getArrayCopy());
71: }
72:
73: public function testCount()
74: {
75: $collection = new RouteCollection();
76: $collection->add('foo', new Route('/foo'));
77:
78: $collection1 = new RouteCollection();
79: $collection1->add('bar', new Route('/bar'));
80: $collection->addCollection($collection1);
81:
82: $this->assertCount(2, $collection);
83: }
84:
85: public function testAddCollection()
86: {
87: $collection = new RouteCollection();
88: $collection->add('foo', new Route('/foo'));
89:
90: $collection1 = new RouteCollection();
91: $collection1->add('bar', $bar = new Route('/bar'));
92: $collection1->add('foo', $foo = new Route('/foo-new'));
93:
94: $collection2 = new RouteCollection();
95: $collection2->add('grandchild', $grandchild = new Route('/grandchild'));
96:
97: $collection1->addCollection($collection2);
98: $collection->addCollection($collection1);
99: $collection->add('last', $last = new Route('/last'));
100:
101: $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'grandchild' => $grandchild, 'last' => $last), $collection->all(),
102: '->addCollection() imports routes of another collection, overrides if necessary and adds them at the end');
103: }
104:
105: public function testAddCollectionWithResources()
106: {
107: $collection = new RouteCollection();
108: $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml'));
109: $collection1 = new RouteCollection();
110: $collection1->addResource($foo1 = new FileResource(__DIR__.'/Fixtures/foo1.xml'));
111: $collection->addCollection($collection1);
112: $this->assertEquals(array($foo, $foo1), $collection->getResources(), '->addCollection() merges resources');
113: }
114:
115: public function testAddDefaultsAndRequirementsAndOptions()
116: {
117: $collection = new RouteCollection();
118: $collection->add('foo', new Route('/{placeholder}'));
119: $collection1 = new RouteCollection();
120: $collection1->add('bar', new Route('/{placeholder}',
121: array('_controller' => 'fixed', 'placeholder' => 'default'), array('placeholder' => '.+'), array('option' => 'value'))
122: );
123: $collection->addCollection($collection1);
124:
125: $collection->addDefaults(array('placeholder' => 'new-default'));
126: $this->assertEquals(array('placeholder' => 'new-default'), $collection->get('foo')->getDefaults(), '->addDefaults() adds defaults to all routes');
127: $this->assertEquals(array('_controller' => 'fixed', 'placeholder' => 'new-default'), $collection->get('bar')->getDefaults(),
128: '->addDefaults() adds defaults to all routes and overwrites existing ones');
129:
130: $collection->addRequirements(array('placeholder' => '\d+'));
131: $this->assertEquals(array('placeholder' => '\d+'), $collection->get('foo')->getRequirements(), '->addRequirements() adds requirements to all routes');
132: $this->assertEquals(array('placeholder' => '\d+'), $collection->get('bar')->getRequirements(),
133: '->addRequirements() adds requirements to all routes and overwrites existing ones');
134:
135: $collection->addOptions(array('option' => 'new-value'));
136: $this->assertEquals(
137: array('option' => 'new-value', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'),
138: $collection->get('bar')->getOptions(), '->addOptions() adds options to all routes and overwrites existing ones'
139: );
140: }
141:
142: public function testAddPrefix()
143: {
144: $collection = new RouteCollection();
145: $collection->add('foo', $foo = new Route('/foo'));
146: $collection2 = new RouteCollection();
147: $collection2->add('bar', $bar = new Route('/bar'));
148: $collection->addCollection($collection2);
149: $collection->addPrefix(' / ');
150: $this->assertSame('/foo', $collection->get('foo')->getPath(), '->addPrefix() trims the prefix and a single slash has no effect');
151: $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'));
152: $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() adds a prefix to all routes');
153: $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPath(), '->addPrefix() adds a prefix to all routes');
154: $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes');
155: $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes');
156: $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes');
157: $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds requirements to all routes');
158: $collection->addPrefix('0');
159: $this->assertEquals('/0/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash');
160: $collection->addPrefix('/ /');
161: $this->assertSame('/ /0/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() can handle spaces if desired');
162: $this->assertSame('/ /0/{admin}/bar', $collection->get('bar')->getPath(), 'the route pattern of an added collection is in synch with the added prefix');
163: }
164:
165: public function testAddPrefixOverridesDefaultsAndRequirements()
166: {
167: $collection = new RouteCollection();
168: $collection->add('foo', $foo = new Route('/foo.{_format}'));
169: $collection->add('bar', $bar = new Route('/bar.{_format}', array(), array('_format' => 'json')));
170: $collection->addPrefix('/admin', array(), array('_format' => 'html'));
171:
172: $this->assertEquals('html', $collection->get('foo')->getRequirement('_format'), '->addPrefix() overrides existing requirements');
173: $this->assertEquals('html', $collection->get('bar')->getRequirement('_format'), '->addPrefix() overrides existing requirements');
174: }
175:
176: public function testResource()
177: {
178: $collection = new RouteCollection();
179: $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml'));
180: $collection->addResource($bar = new FileResource(__DIR__.'/Fixtures/bar.xml'));
181: $collection->addResource(new FileResource(__DIR__.'/Fixtures/foo.xml'));
182:
183: $this->assertEquals(array($foo, $bar), $collection->getResources(),
184: '->addResource() adds a resource and getResources() only returns unique ones by comparing the string representation');
185: }
186:
187: public function testUniqueRouteWithGivenName()
188: {
189: $collection1 = new RouteCollection();
190: $collection1->add('foo', new Route('/old'));
191: $collection2 = new RouteCollection();
192: $collection3 = new RouteCollection();
193: $collection3->add('foo', $new = new Route('/new'));
194:
195: $collection2->addCollection($collection3);
196: $collection1->addCollection($collection2);
197:
198: $this->assertSame($new, $collection1->get('foo'), '->get() returns new route that overrode previous one');
199:
200: $this->assertCount(1, $collection1->getIterator(), '->addCollection() removes previous routes when adding new routes with the same name');
201: }
202:
203: public function testGet()
204: {
205: $collection1 = new RouteCollection();
206: $collection1->add('a', $a = new Route('/a'));
207: $collection2 = new RouteCollection();
208: $collection2->add('b', $b = new Route('/b'));
209: $collection1->addCollection($collection2);
210: $collection1->add('$péß^a|', $c = new Route('/special'));
211:
212: $this->assertSame($b, $collection1->get('b'), '->get() returns correct route in child collection');
213: $this->assertSame($c, $collection1->get('$péß^a|'), '->get() can handle special characters');
214: $this->assertNull($collection2->get('a'), '->get() does not return the route defined in parent collection');
215: $this->assertNull($collection1->get('non-existent'), '->get() returns null when route does not exist');
216: $this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection');
217: }
218:
219: public function testRemove()
220: {
221: $collection = new RouteCollection();
222: $collection->add('foo', $foo = new Route('/foo'));
223:
224: $collection1 = new RouteCollection();
225: $collection1->add('bar', $bar = new Route('/bar'));
226: $collection->addCollection($collection1);
227: $collection->add('last', $last = new Route('/last'));
228:
229: $collection->remove('foo');
230: $this->assertSame(array('bar' => $bar, 'last' => $last), $collection->all(), '->remove() can remove a single route');
231: $collection->remove(array('bar', 'last'));
232: $this->assertSame(array(), $collection->all(), '->remove() accepts an array and can remove multiple routes at once');
233: }
234:
235: public function testSetHost()
236: {
237: $collection = new RouteCollection();
238: $routea = new Route('/a');
239: $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net');
240: $collection->add('a', $routea);
241: $collection->add('b', $routeb);
242:
243: $collection->setHost('{locale}.example.com');
244:
245: $this->assertEquals('{locale}.example.com', $routea->getHost());
246: $this->assertEquals('{locale}.example.com', $routeb->getHost());
247: }
248:
249: public function testSetCondition()
250: {
251: $collection = new RouteCollection();
252: $routea = new Route('/a');
253: $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net', array(), array(), 'context.getMethod() == "GET"');
254: $collection->add('a', $routea);
255: $collection->add('b', $routeb);
256:
257: $collection->setCondition('context.getMethod() == "POST"');
258:
259: $this->assertEquals('context.getMethod() == "POST"', $routea->getCondition());
260: $this->assertEquals('context.getMethod() == "POST"', $routeb->getCondition());
261: }
262:
263: public function testClone()
264: {
265: $collection = new RouteCollection();
266: $collection->add('a', new Route('/a'));
267: $collection->add('b', new Route('/b', array('placeholder' => 'default'), array('placeholder' => '.+')));
268:
269: $clonedCollection = clone $collection;
270:
271: $this->assertCount(2, $clonedCollection);
272: $this->assertEquals($collection->get('a'), $clonedCollection->get('a'));
273: $this->assertNotSame($collection->get('a'), $clonedCollection->get('a'));
274: $this->assertEquals($collection->get('b'), $clonedCollection->get('b'));
275: $this->assertNotSame($collection->get('b'), $clonedCollection->get('b'));
276: }
277:
278: public function testSetSchemes()
279: {
280: $collection = new RouteCollection();
281: $routea = new Route('/a', array(), array(), array(), '', 'http');
282: $routeb = new Route('/b');
283: $collection->add('a', $routea);
284: $collection->add('b', $routeb);
285:
286: $collection->setSchemes(array('http', 'https'));
287:
288: $this->assertEquals(array('http', 'https'), $routea->getSchemes());
289: $this->assertEquals(array('http', 'https'), $routeb->getSchemes());
290: }
291:
292: public function testSetMethods()
293: {
294: $collection = new RouteCollection();
295: $routea = new Route('/a', array(), array(), array(), '', array(), array('GET', 'POST'));
296: $routeb = new Route('/b');
297: $collection->add('a', $routea);
298: $collection->add('b', $routeb);
299:
300: $collection->setMethods('PUT');
301:
302: $this->assertEquals(array('PUT'), $routea->getMethods());
303: $this->assertEquals(array('PUT'), $routeb->getMethods());
304: }
305: }
306: