RoutingTest.php 15 KB

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