RoutingTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <?php
  2. namespace Test\AppFramework\Routing;
  3. use OC\AppFramework\DependencyInjection\DIContainer;
  4. use OC\AppFramework\Routing\RouteActionHandler;
  5. use OC\AppFramework\Routing\RouteConfig;
  6. use OCP\ILogger;
  7. class RoutingTest extends \Test\TestCase
  8. {
  9. public function testSimpleRoute()
  10. {
  11. $routes = array('routes' => array(
  12. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'GET')
  13. ));
  14. $this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
  15. }
  16. public function testSimpleOCSRoute() {
  17. $routes = ['ocs' => [
  18. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'GET']
  19. ]
  20. ];
  21. $this->assertSimpleOCSRoute($routes, 'folders.open', 'GET', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open');
  22. }
  23. public function testSimpleRouteWithMissingVerb()
  24. {
  25. $routes = array('routes' => array(
  26. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open')
  27. ));
  28. $this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
  29. }
  30. public function testSimpleOCSRouteWithMissingVerb() {
  31. $routes = ['ocs' => [
  32. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open']
  33. ]
  34. ];
  35. $this->assertSimpleOCSRoute($routes, 'folders.open', 'GET', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open');
  36. }
  37. public function testSimpleRouteWithLowercaseVerb()
  38. {
  39. $routes = array('routes' => array(
  40. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete')
  41. ));
  42. $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open');
  43. }
  44. public function testSimpleOCSRouteWithLowercaseVerb() {
  45. $routes = ['ocs' => [
  46. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
  47. ]
  48. ];
  49. $this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open');
  50. }
  51. public function testSimpleRouteWithRequirements()
  52. {
  53. $routes = array('routes' => array(
  54. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'requirements' => array('something'))
  55. ));
  56. $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array('something'));
  57. }
  58. public function testSimpleOCSRouteWithRequirements() {
  59. $routes = ['ocs' => [
  60. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'requirements' => ['something']]
  61. ]
  62. ];
  63. $this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open', ['something']);
  64. }
  65. public function testSimpleRouteWithDefaults()
  66. {
  67. $routes = array('routes' => array(
  68. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', array(), 'defaults' => array('param' => 'foobar'))
  69. ));
  70. $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array(), array('param' => 'foobar'));
  71. }
  72. public function testSimpleOCSRouteWithDefaults() {
  73. $routes = ['ocs' => [
  74. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'defaults' => ['param' => 'foobar']]
  75. ]
  76. ];
  77. $this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open', [], ['param' => 'foobar']);
  78. }
  79. public function testSimpleRouteWithPostfix()
  80. {
  81. $routes = array('routes' => array(
  82. array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'postfix' => '_something')
  83. ));
  84. $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array(), array(), '_something');
  85. }
  86. public function testSimpleOCSRouteWithPostfix() {
  87. $routes = ['ocs' => [
  88. ['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'postfix' => '_something']
  89. ]
  90. ];
  91. $this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/apps/app1/folders/{folderId}/open', 'FoldersController', 'open', [], [], '_something');
  92. }
  93. /**
  94. * @expectedException \UnexpectedValueException
  95. */
  96. public function testSimpleRouteWithBrokenName()
  97. {
  98. $routes = array('routes' => array(
  99. array('name' => 'folders_open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete')
  100. ));
  101. // router mock
  102. $router = $this->getMockBuilder('\OC\Route\Router')
  103. ->setMethods(['create'])
  104. ->setConstructorArgs([$this->getMockBuilder(ILogger::class)->getMock()])
  105. ->getMock();
  106. // load route configuration
  107. $container = new DIContainer('app1');
  108. $config = new RouteConfig($container, $router, $routes);
  109. $config->register();
  110. }
  111. /**
  112. * @expectedException \UnexpectedValueException
  113. */
  114. public function testSimpleOCSRouteWithBrokenName() {
  115. $routes = ['ocs' => [
  116. ['name' => 'folders_open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
  117. ]];
  118. // router mock
  119. $router = $this->getMockBuilder('\OC\Route\Router')
  120. ->setMethods(['create'])
  121. ->setConstructorArgs([$this->getMockBuilder(ILogger::class)->getMock()])
  122. ->getMock();
  123. // load route configuration
  124. $container = new DIContainer('app1');
  125. $config = new RouteConfig($container, $router, $routes);
  126. $config->register();
  127. }
  128. public function testSimpleRouteWithUnderScoreNames()
  129. {
  130. $routes = array('routes' => array(
  131. array('name' => 'admin_folders#open_current', 'url' => '/folders/{folderId}/open', 'verb' => 'delete')
  132. ));
  133. $this->assertSimpleRoute($routes, 'admin_folders.open_current', 'DELETE', '/folders/{folderId}/open', 'AdminFoldersController', 'openCurrent');
  134. }
  135. public function testSimpleOCSRouteWithUnderScoreNames() {
  136. $routes = ['ocs' => [
  137. ['name' => 'admin_folders#open_current', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
  138. ]];
  139. $this->assertSimpleOCSRoute($routes, 'admin_folders.open_current', 'DELETE', '/apps/app1/folders/{folderId}/open', 'AdminFoldersController', 'openCurrent');
  140. }
  141. public function testResource()
  142. {
  143. $routes = array('resources' => array('account' => array('url' => '/accounts')));
  144. $this->assertResource($routes, 'account', '/accounts', 'AccountController', 'id');
  145. }
  146. public function testResourceWithUnderScoreName()
  147. {
  148. $routes = array('resources' => array('admin_accounts' => array('url' => '/admin/accounts')));
  149. $this->assertResource($routes, 'admin_accounts', '/admin/accounts', 'AdminAccountsController', 'id');
  150. }
  151. /**
  152. * @param string $name
  153. * @param string $verb
  154. * @param string $url
  155. * @param string $controllerName
  156. * @param string $actionName
  157. */
  158. private function assertSimpleRoute($routes, $name, $verb, $url, $controllerName, $actionName, array $requirements=array(), array $defaults=array(), $postfix='')
  159. {
  160. if ($postfix) {
  161. $name .= $postfix;
  162. }
  163. // route mocks
  164. $container = new DIContainer('app1');
  165. $route = $this->mockRoute($container, $verb, $controllerName, $actionName, $requirements, $defaults);
  166. // router mock
  167. $router = $this->getMockBuilder('\OC\Route\Router')
  168. ->setMethods(['create'])
  169. ->setConstructorArgs([$this->getMockBuilder(ILogger::class)->getMock()])
  170. ->getMock();
  171. // we expect create to be called once:
  172. $router
  173. ->expects($this->once())
  174. ->method('create')
  175. ->with($this->equalTo('app1.' . $name), $this->equalTo($url))
  176. ->will($this->returnValue($route));
  177. // load route configuration
  178. $config = new RouteConfig($container, $router, $routes);
  179. $config->register();
  180. }
  181. /**
  182. * @param $routes
  183. * @param string $name
  184. * @param string $verb
  185. * @param string $url
  186. * @param string $controllerName
  187. * @param string $actionName
  188. * @param array $requirements
  189. * @param array $defaults
  190. * @param string $postfix
  191. */
  192. private function assertSimpleOCSRoute($routes,
  193. $name,
  194. $verb,
  195. $url,
  196. $controllerName,
  197. $actionName,
  198. array $requirements=array(),
  199. array $defaults=array(),
  200. $postfix='')
  201. {
  202. if ($postfix) {
  203. $name .= $postfix;
  204. }
  205. // route mocks
  206. $container = new DIContainer('app1');
  207. $route = $this->mockRoute($container, $verb, $controllerName, $actionName, $requirements, $defaults);
  208. // router mock
  209. $router = $this->getMockBuilder('\OC\Route\Router')
  210. ->setMethods(['create'])
  211. ->setConstructorArgs([$this->getMockBuilder(ILogger::class)->getMock()])
  212. ->getMock();
  213. // we expect create to be called once:
  214. $router
  215. ->expects($this->once())
  216. ->method('create')
  217. ->with($this->equalTo('ocs.app1.' . $name), $this->equalTo($url))
  218. ->will($this->returnValue($route));
  219. // load route configuration
  220. $config = new RouteConfig($container, $router, $routes);
  221. $config->register();
  222. }
  223. /**
  224. * @param string $resourceName
  225. * @param string $url
  226. * @param string $controllerName
  227. * @param string $paramName
  228. */
  229. private function assertResource($yaml, $resourceName, $url, $controllerName, $paramName)
  230. {
  231. // router mock
  232. $router = $this->getMockBuilder('\OC\Route\Router')
  233. ->setMethods(['create'])
  234. ->setConstructorArgs([$this->getMockBuilder(ILogger::class)->getMock()])
  235. ->getMock();
  236. // route mocks
  237. $container = new DIContainer('app1');
  238. $indexRoute = $this->mockRoute($container, 'GET', $controllerName, 'index');
  239. $showRoute = $this->mockRoute($container, 'GET', $controllerName, 'show');
  240. $createRoute = $this->mockRoute($container, 'POST', $controllerName, 'create');
  241. $updateRoute = $this->mockRoute($container, 'PUT', $controllerName, 'update');
  242. $destroyRoute = $this->mockRoute($container, 'DELETE', $controllerName, 'destroy');
  243. $urlWithParam = $url . '/{' . $paramName . '}';
  244. // we expect create to be called once:
  245. $router
  246. ->expects($this->at(0))
  247. ->method('create')
  248. ->with($this->equalTo('app1.' . $resourceName . '.index'), $this->equalTo($url))
  249. ->will($this->returnValue($indexRoute));
  250. $router
  251. ->expects($this->at(1))
  252. ->method('create')
  253. ->with($this->equalTo('app1.' . $resourceName . '.show'), $this->equalTo($urlWithParam))
  254. ->will($this->returnValue($showRoute));
  255. $router
  256. ->expects($this->at(2))
  257. ->method('create')
  258. ->with($this->equalTo('app1.' . $resourceName . '.create'), $this->equalTo($url))
  259. ->will($this->returnValue($createRoute));
  260. $router
  261. ->expects($this->at(3))
  262. ->method('create')
  263. ->with($this->equalTo('app1.' . $resourceName . '.update'), $this->equalTo($urlWithParam))
  264. ->will($this->returnValue($updateRoute));
  265. $router
  266. ->expects($this->at(4))
  267. ->method('create')
  268. ->with($this->equalTo('app1.' . $resourceName . '.destroy'), $this->equalTo($urlWithParam))
  269. ->will($this->returnValue($destroyRoute));
  270. // load route configuration
  271. $config = new RouteConfig($container, $router, $yaml);
  272. $config->register();
  273. }
  274. /**
  275. * @param DIContainer $container
  276. * @param string $verb
  277. * @param string $controllerName
  278. * @param string $actionName
  279. * @param array $requirements
  280. * @param array $defaults
  281. * @return \PHPUnit_Framework_MockObject_MockObject
  282. */
  283. private function mockRoute(
  284. DIContainer $container,
  285. $verb,
  286. $controllerName,
  287. $actionName,
  288. array $requirements=array(),
  289. array $defaults=array()
  290. ) {
  291. $route = $this->getMockBuilder('\OC\Route\Route')
  292. ->setMethods(['method', 'action', 'requirements', 'defaults'])
  293. ->disableOriginalConstructor()
  294. ->getMock();
  295. $route
  296. ->expects($this->exactly(1))
  297. ->method('method')
  298. ->with($this->equalTo($verb))
  299. ->will($this->returnValue($route));
  300. $route
  301. ->expects($this->exactly(1))
  302. ->method('action')
  303. ->with($this->equalTo(new RouteActionHandler($container, $controllerName, $actionName)))
  304. ->will($this->returnValue($route));
  305. if(count($requirements) > 0) {
  306. $route
  307. ->expects($this->exactly(1))
  308. ->method('requirements')
  309. ->with($this->equalTo($requirements))
  310. ->will($this->returnValue($route));
  311. }
  312. if (count($defaults) > 0) {
  313. $route
  314. ->expects($this->exactly(1))
  315. ->method('defaults')
  316. ->with($this->equalTo($defaults))
  317. ->will($this->returnValue($route));
  318. }
  319. return $route;
  320. }
  321. }
  322. /*
  323. #
  324. # sample routes.yaml for ownCloud
  325. #
  326. # the section simple describes one route
  327. routes:
  328. - name: folders#open
  329. url: /folders/{folderId}/open
  330. verb: GET
  331. # controller: name.split()[0]
  332. # action: name.split()[1]
  333. # for a resource following actions will be generated:
  334. # - index
  335. # - create
  336. # - show
  337. # - update
  338. # - destroy
  339. # - new
  340. resources:
  341. accounts:
  342. url: /accounts
  343. folders:
  344. url: /accounts/{accountId}/folders
  345. # actions can be used to define additional actions on the resource
  346. actions:
  347. - name: validate
  348. verb: GET
  349. on-collection: false
  350. * */