You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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