AnnotationClassLoaderTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Routing\Tests\Loader;
  11. use Symfony\Component\Routing\Annotation\Route;
  12. class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
  13. {
  14. protected $loader;
  15. private $reader;
  16. protected function setUp()
  17. {
  18. parent::setUp();
  19. $this->reader = $this->getReader();
  20. $this->loader = $this->getClassLoader($this->reader);
  21. }
  22. /**
  23. * @expectedException \InvalidArgumentException
  24. */
  25. public function testLoadMissingClass()
  26. {
  27. $this->loader->load('MissingClass');
  28. }
  29. /**
  30. * @expectedException \InvalidArgumentException
  31. */
  32. public function testLoadAbstractClass()
  33. {
  34. $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass');
  35. }
  36. /**
  37. * @dataProvider provideTestSupportsChecksResource
  38. */
  39. public function testSupportsChecksResource($resource, $expectedSupports)
  40. {
  41. $this->assertSame($expectedSupports, $this->loader->supports($resource), '->supports() returns true if the resource is loadable');
  42. }
  43. public function provideTestSupportsChecksResource()
  44. {
  45. return array(
  46. array('class', true),
  47. array('\fully\qualified\class\name', true),
  48. array('namespaced\class\without\leading\slash', true),
  49. array('ÿClassWithLegalSpecialCharacters', true),
  50. array('5', false),
  51. array('foo.foo', false),
  52. array(null, false),
  53. );
  54. }
  55. public function testSupportsChecksTypeIfSpecified()
  56. {
  57. $this->assertTrue($this->loader->supports('class', 'annotation'), '->supports() checks the resource type if specified');
  58. $this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified');
  59. }
  60. public function getLoadTests()
  61. {
  62. return array(
  63. array(
  64. 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
  65. array('name' => 'route1', 'path' => '/path'),
  66. array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
  67. ),
  68. array(
  69. 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
  70. array('defaults' => array('arg2' => 'foo'), 'requirements' => array('arg3' => '\w+')),
  71. array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
  72. ),
  73. array(
  74. 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
  75. array('options' => array('foo' => 'bar')),
  76. array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
  77. ),
  78. array(
  79. 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
  80. array('schemes' => array('https'), 'methods' => array('GET')),
  81. array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
  82. ),
  83. array(
  84. 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
  85. array('condition' => 'context.getMethod() == "GET"'),
  86. array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
  87. ),
  88. );
  89. }
  90. /**
  91. * @dataProvider getLoadTests
  92. */
  93. public function testLoad($className, $routeData = array(), $methodArgs = array())
  94. {
  95. $routeData = array_replace(array(
  96. 'name' => 'route',
  97. 'path' => '/',
  98. 'requirements' => array(),
  99. 'options' => array(),
  100. 'defaults' => array(),
  101. 'schemes' => array(),
  102. 'methods' => array(),
  103. 'condition' => '',
  104. ), $routeData);
  105. $this->reader
  106. ->expects($this->once())
  107. ->method('getMethodAnnotations')
  108. ->will($this->returnValue(array($this->getAnnotatedRoute($routeData))))
  109. ;
  110. $routeCollection = $this->loader->load($className);
  111. $route = $routeCollection->get($routeData['name']);
  112. $this->assertSame($routeData['path'], $route->getPath(), '->load preserves path annotation');
  113. $this->assertCount(
  114. \count($routeData['requirements']),
  115. array_intersect_assoc($routeData['requirements'], $route->getRequirements()),
  116. '->load preserves requirements annotation'
  117. );
  118. $this->assertCount(
  119. \count($routeData['options']),
  120. array_intersect_assoc($routeData['options'], $route->getOptions()),
  121. '->load preserves options annotation'
  122. );
  123. $this->assertCount(
  124. \count($routeData['defaults']),
  125. $route->getDefaults(),
  126. '->load preserves defaults annotation'
  127. );
  128. $this->assertEquals($routeData['schemes'], $route->getSchemes(), '->load preserves schemes annotation');
  129. $this->assertEquals($routeData['methods'], $route->getMethods(), '->load preserves methods annotation');
  130. $this->assertSame($routeData['condition'], $route->getCondition(), '->load preserves condition annotation');
  131. }
  132. public function testClassRouteLoad()
  133. {
  134. $classRouteData = array(
  135. 'name' => 'prefix_',
  136. 'path' => '/prefix',
  137. 'schemes' => array('https'),
  138. 'methods' => array('GET'),
  139. );
  140. $methodRouteData = array(
  141. 'name' => 'route1',
  142. 'path' => '/path',
  143. 'schemes' => array('http'),
  144. 'methods' => array('POST', 'PUT'),
  145. );
  146. $this->reader
  147. ->expects($this->once())
  148. ->method('getClassAnnotation')
  149. ->will($this->returnValue($this->getAnnotatedRoute($classRouteData)))
  150. ;
  151. $this->reader
  152. ->expects($this->once())
  153. ->method('getMethodAnnotations')
  154. ->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData))))
  155. ;
  156. $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass');
  157. $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']);
  158. $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path');
  159. $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes');
  160. $this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods');
  161. }
  162. public function testInvokableClassRouteLoad()
  163. {
  164. $classRouteData = array(
  165. 'name' => 'route1',
  166. 'path' => '/',
  167. 'schemes' => array('https'),
  168. 'methods' => array('GET'),
  169. );
  170. $this->reader
  171. ->expects($this->exactly(1))
  172. ->method('getClassAnnotations')
  173. ->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData))))
  174. ;
  175. $this->reader
  176. ->expects($this->once())
  177. ->method('getMethodAnnotations')
  178. ->will($this->returnValue(array()))
  179. ;
  180. $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
  181. $route = $routeCollection->get($classRouteData['name']);
  182. $this->assertSame($classRouteData['path'], $route->getPath(), '->load preserves class route path');
  183. $this->assertEquals($classRouteData['schemes'], $route->getSchemes(), '->load preserves class route schemes');
  184. $this->assertEquals($classRouteData['methods'], $route->getMethods(), '->load preserves class route methods');
  185. }
  186. public function testInvokableClassMultipleRouteLoad()
  187. {
  188. $classRouteData1 = array(
  189. 'name' => 'route1',
  190. 'path' => '/1',
  191. 'schemes' => array('https'),
  192. 'methods' => array('GET'),
  193. );
  194. $classRouteData2 = array(
  195. 'name' => 'route2',
  196. 'path' => '/2',
  197. 'schemes' => array('https'),
  198. 'methods' => array('GET'),
  199. );
  200. $this->reader
  201. ->expects($this->exactly(1))
  202. ->method('getClassAnnotations')
  203. ->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData1), $this->getAnnotatedRoute($classRouteData2))))
  204. ;
  205. $this->reader
  206. ->expects($this->once())
  207. ->method('getMethodAnnotations')
  208. ->will($this->returnValue(array()))
  209. ;
  210. $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
  211. $route = $routeCollection->get($classRouteData1['name']);
  212. $this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path');
  213. $this->assertEquals($classRouteData1['schemes'], $route->getSchemes(), '->load preserves class route schemes');
  214. $this->assertEquals($classRouteData1['methods'], $route->getMethods(), '->load preserves class route methods');
  215. $route = $routeCollection->get($classRouteData2['name']);
  216. $this->assertSame($classRouteData2['path'], $route->getPath(), '->load preserves class route path');
  217. $this->assertEquals($classRouteData2['schemes'], $route->getSchemes(), '->load preserves class route schemes');
  218. $this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods');
  219. }
  220. public function testInvokableClassWithMethodRouteLoad()
  221. {
  222. $classRouteData = array(
  223. 'name' => 'route1',
  224. 'path' => '/prefix',
  225. 'schemes' => array('https'),
  226. 'methods' => array('GET'),
  227. );
  228. $methodRouteData = array(
  229. 'name' => 'route2',
  230. 'path' => '/path',
  231. 'schemes' => array('http'),
  232. 'methods' => array('POST', 'PUT'),
  233. );
  234. $this->reader
  235. ->expects($this->once())
  236. ->method('getClassAnnotation')
  237. ->will($this->returnValue($this->getAnnotatedRoute($classRouteData)))
  238. ;
  239. $this->reader
  240. ->expects($this->once())
  241. ->method('getMethodAnnotations')
  242. ->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData))))
  243. ;
  244. $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
  245. $route = $routeCollection->get($classRouteData['name']);
  246. $this->assertNull($route, '->load ignores class route');
  247. $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']);
  248. $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path');
  249. $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes');
  250. $this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods');
  251. }
  252. private function getAnnotatedRoute($data)
  253. {
  254. return new Route($data);
  255. }
  256. }