RouteMatcherTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. namespace Mpociot\ApiDoc\Tests;
  3. use Dingo\Api\Routing\Route as DingoRoute;
  4. use Dingo\Api\Routing\Router;
  5. use Illuminate\Routing\Route;
  6. use Mpociot\ApiDoc\Tools\RouteMatcher;
  7. use Orchestra\Testbench\TestCase;
  8. use Mpociot\ApiDoc\Generators\LaravelGenerator;
  9. use Mpociot\ApiDoc\Tests\Fixtures\TestController;
  10. use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
  11. use Illuminate\Support\Facades\Route as RouteFacade;
  12. class RouteMatcherTest extends TestCase
  13. {
  14. /**
  15. * @var RouteMatcher
  16. */
  17. private $matcher;
  18. protected function setUp()
  19. {
  20. parent::setUp();
  21. $this->matcher = new RouteMatcher();
  22. }
  23. protected function getPackageProviders($app)
  24. {
  25. return [
  26. \Dingo\Api\Provider\LaravelServiceProvider::class,
  27. ];
  28. }
  29. public function testRespectsDomainsRuleForLaravelRouter()
  30. {
  31. $this->registerLaravelRoutes();
  32. $routeRules[0]['match']['prefixes'] = ['*'];
  33. $routeRules[0]['match']['domains'] = ['*'];
  34. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  35. $this->assertCount(12, $routes);
  36. $routeRules[0]['match']['domains'] = ['domain1.*', 'domain2.*'];
  37. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  38. $this->assertCount(12, $routes);
  39. $routeRules[0]['match']['domains'] = ['domain1.*'];
  40. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  41. $this->assertCount(6, $routes);
  42. foreach ($routes as $route){
  43. $this->assertContains('domain1', $route['route']->getDomain());
  44. }
  45. $routeRules[0]['match']['domains'] = ['domain2.*'];
  46. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  47. $this->assertCount(6, $routes);
  48. foreach ($routes as $route){
  49. $this->assertContains('domain2', $route['route']->getDomain());
  50. }
  51. }
  52. public function testRespectsDomainsRuleForDingoRouter()
  53. {
  54. $this->registerDingoRoutes();
  55. $routeRules[0]['match']['versions'] = ['v1'];
  56. $routeRules[0]['match']['prefixes'] = ['*'];
  57. $routeRules[0]['match']['domains'] = ['*'];
  58. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  59. $this->assertCount(12, $routes);
  60. $routeRules[0]['match']['domains'] = ['domain1.*', 'domain2.*'];
  61. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  62. $this->assertCount(12, $routes);
  63. $routeRules[0]['match']['domains'] = ['domain1.*'];
  64. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  65. $this->assertCount(6, $routes);
  66. foreach ($routes as $route){
  67. $this->assertContains('domain1', $route['route']->getDomain());
  68. }
  69. $routeRules[0]['match']['domains'] = ['domain2.*'];
  70. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  71. $this->assertCount(6, $routes);
  72. foreach ($routes as $route){
  73. $this->assertContains('domain2', $route['route']->getDomain());
  74. }
  75. }
  76. public function testRespectsPrefixesRuleForLaravelRouter()
  77. {
  78. $this->registerLaravelRoutes();
  79. $routeRules[0]['match']['domains'] = ['*'];
  80. $routeRules[0]['match']['prefixes'] = ['*'];
  81. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  82. $this->assertCount(12, $routes);
  83. $routeRules[0]['match']['prefixes'] = ['prefix1/*', 'prefix2/*'];
  84. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  85. $this->assertCount(8, $routes);
  86. $routeRules[0]['match']['prefixes'] = ['prefix1/*'];
  87. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  88. $this->assertCount(4, $routes);
  89. foreach ($routes as $route){
  90. $this->assertTrue(str_is('prefix1/*', $route['route']->uri()));
  91. }
  92. $routeRules[0]['match']['prefixes'] = ['prefix2/*'];
  93. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  94. $this->assertCount(4, $routes);
  95. foreach ($routes as $route){
  96. $this->assertTrue(str_is('prefix2/*', $route['route']->uri()));
  97. }
  98. }
  99. public function testRespectsPrefixesRuleForDingoRouter()
  100. {
  101. $this->registerDingoRoutes();
  102. $routeRules[0]['match']['versions'] = ['v1'];
  103. $routeRules[0]['match']['domains'] = ['*'];
  104. $routeRules[0]['match']['prefixes'] = ['*'];
  105. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  106. $this->assertCount(12, $routes);
  107. $routeRules[0]['match']['prefixes'] = ['prefix1/*', 'prefix2/*'];
  108. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  109. $this->assertCount(8, $routes);
  110. $routeRules[0]['match']['prefixes'] = ['prefix1/*'];
  111. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  112. $this->assertCount(4, $routes);
  113. foreach ($routes as $route){
  114. $this->assertTrue(str_is('prefix1/*', $route['route']->uri()));
  115. }
  116. $routeRules[0]['match']['prefixes'] = ['prefix2/*'];
  117. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  118. $this->assertCount(4, $routes);
  119. foreach ($routes as $route){
  120. $this->assertTrue(str_is('prefix2/*', $route['route']->uri()));
  121. }
  122. }
  123. public function testRespectsVersionsRuleForDingoRouter()
  124. {
  125. $this->registerDingoRoutes();
  126. $routeRules[0]['match']['versions'] = ['v2'];
  127. $routeRules[0]['match']['domains'] = ['*'];
  128. $routeRules[0]['match']['prefixes'] = ['*'];
  129. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  130. $this->assertCount(6, $routes);
  131. foreach ($routes as $route){
  132. $this->assertNotEmpty(array_intersect($route['route']->versions(), ['v2']));
  133. }
  134. $routeRules[0]['match']['versions'] = ['v1', 'v2'];
  135. $routeRules[0]['match']['domains'] = ['*'];
  136. $routeRules[0]['match']['prefixes'] = ['*'];
  137. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  138. $this->assertCount(18, $routes);
  139. }
  140. public function testWillIncludeRouteIfListedExplicitlyForLaravelRouter()
  141. {
  142. $this->registerLaravelRoutes();
  143. $mustInclude = 'domain1-1';
  144. $routeRules[0]['include'] = [$mustInclude];
  145. $routeRules[0]['match']['domains'] = ['domain1.*'];
  146. $routeRules[0]['match']['prefixes'] = ['prefix1/*'];
  147. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  148. $oddRuleOut = collect($routes)->filter(function ($route) use ($mustInclude) {
  149. return $route['route']->getName() === $mustInclude;
  150. });
  151. $this->assertCount(1, $oddRuleOut);
  152. }
  153. public function testWillIncludeRouteIfListedExplicitlyForDingoRouter()
  154. {
  155. $this->registerDingoRoutes();
  156. $mustInclude = 'v2.domain2';
  157. $routeRules = [
  158. [
  159. 'match' => [
  160. 'domains' => ['domain1.*'],
  161. 'prefixes' => ['prefix1/*'],
  162. 'versions' => ['v1']
  163. ],
  164. 'include' => [$mustInclude],
  165. ],
  166. ];
  167. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  168. $oddRuleOut = collect($routes)->filter(function ($route) use ($mustInclude) {
  169. return $route['route']->getName() === $mustInclude;
  170. });
  171. $this->assertCount(1, $oddRuleOut);
  172. }
  173. public function testWillExcludeRouteIfListedExplicitlyForLaravelRouter()
  174. {
  175. $this->registerLaravelRoutes();
  176. $mustNotInclude = 'prefix1.domain1-1';
  177. $routeRules[0]['exclude'] = [$mustNotInclude];
  178. $routeRules[0]['match']['domains'] = ['domain1.*'];
  179. $routeRules[0]['match']['prefixes'] = ['prefix1/*'];
  180. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  181. $oddRuleOut = collect($routes)->filter(function ($route) use ($mustNotInclude) {
  182. return $route['route']->getName() === $mustNotInclude;
  183. });
  184. $this->assertCount(0, $oddRuleOut);
  185. }
  186. public function testWillExcludeRouteIfListedExplicitlyForDingoRouter()
  187. {
  188. $this->registerDingoRoutes();
  189. $mustNotInclude = 'v2.domain2';
  190. $routeRules = [
  191. [
  192. 'match' => [
  193. 'domains' => ['domain2.*'],
  194. 'prefixes' => ['*'],
  195. 'versions' => ['v2']
  196. ],
  197. 'exclude' => [$mustNotInclude],
  198. ],
  199. ];
  200. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  201. $oddRuleOut = collect($routes)->filter(function ($route) use ($mustNotInclude) {
  202. return $route['route']->getName() === $mustNotInclude;
  203. });
  204. $this->assertCount(0, $oddRuleOut);
  205. }
  206. public function testMergesRoutesFromDifferentRuleGroupsForLaravelRouter()
  207. {
  208. $this->registerLaravelRoutes();
  209. $routeRules = [
  210. [
  211. 'match' => [
  212. 'domains' => ['domain1.*'],
  213. 'prefixes' => ['prefix1/*'],
  214. ],
  215. ],
  216. [
  217. 'match' => [
  218. 'domains' => ['domain2.*'],
  219. 'prefixes' => ['prefix2*'],
  220. ],
  221. ],
  222. ];
  223. $routes = $this->matcher->getRoutesToBeDocumented($routeRules);
  224. $this->assertCount(4, $routes);
  225. $routes = collect($routes);
  226. $firstRuleGroup = $routes->filter(function ($route) {
  227. return str_is('prefix1/*', $route['route']->uri())
  228. && str_is('domain1.*', $route['route']->getDomain());
  229. });
  230. $this->assertCount(2, $firstRuleGroup);
  231. $secondRuleGroup = $routes->filter(function ($route) {
  232. return str_is('prefix2/*', $route['route']->uri())
  233. && str_is('domain2.*', $route['route']->getDomain());
  234. });
  235. $this->assertCount(2, $secondRuleGroup);
  236. }
  237. public function testMergesRoutesFromDifferentRuleGroupsForDingoRouter()
  238. {
  239. $this->registerDingoRoutes();
  240. $routeRules = [
  241. [
  242. 'match' => [
  243. 'domains' => ['*'],
  244. 'prefixes' => ['*'],
  245. 'versions' => ['v1'],
  246. ],
  247. ],
  248. [
  249. 'match' => [
  250. 'domains' => ['*'],
  251. 'prefixes' => ['*'],
  252. 'versions' => ['v2'],
  253. ],
  254. ],
  255. ];
  256. $routes = $this->matcher->getDingoRoutesToBeDocumented($routeRules);
  257. $this->assertCount(18, $routes);
  258. $routes = collect($routes);
  259. $firstRuleGroup = $routes->filter(function ($route) {
  260. return !empty(array_intersect($route['route']->versions(), ['v1']));
  261. });
  262. $this->assertCount(12, $firstRuleGroup);
  263. $secondRuleGroup = $routes->filter(function ($route) {
  264. return !empty(array_intersect($route['route']->versions(), ['v2']));
  265. });
  266. $this->assertCount(6, $secondRuleGroup);
  267. }
  268. private function registerLaravelRoutes()
  269. {
  270. RouteFacade::group(['domain' => 'domain1.app.test'], function () {
  271. RouteFacade::post('/domain1-1', function () { return 'hi'; })->name('domain1-1');
  272. RouteFacade::get('domain1-2', function () { return 'hi'; })->name('domain1-2');
  273. RouteFacade::get('/prefix1/domain1-1', function () { return 'hi'; })->name('prefix1.domain1-1');
  274. RouteFacade::get('prefix1/domain1-2', function () { return 'hi'; })->name('prefix1.domain1-2');
  275. RouteFacade::get('/prefix2/domain1-1', function () { return 'hi'; })->name('prefix2.domain1-1');
  276. RouteFacade::get('prefix2/domain1-2', function () { return 'hi'; })->name('prefix2.domain1-2');
  277. });
  278. RouteFacade::group(['domain' => 'domain2.app.test'], function () {
  279. RouteFacade::post('/domain2-1', function () { return 'hi'; })->name('domain2-1');
  280. RouteFacade::get('domain2-2', function () { return 'hi'; })->name('domain2-2');
  281. RouteFacade::get('/prefix1/domain2-1', function () { return 'hi'; })->name('prefix1.domain2-1');
  282. RouteFacade::get('prefix1/domain2-2', function () { return 'hi'; })->name('prefix1.domain2-2');
  283. RouteFacade::get('/prefix2/domain2-1', function () { return 'hi'; })->name('prefix2.domain2-1');
  284. RouteFacade::get('prefix2/domain2-2', function () { return 'hi'; })->name('prefix2.domain2-2');
  285. });
  286. }
  287. private function registerDingoRoutes()
  288. {
  289. $api = app('api.router');
  290. $api->version('v1', function (Router $api) {
  291. $api->group(['domain' => 'domain1.app.test'], function (Router $api) {
  292. $api->post('/domain1-1', function () { return 'hi'; })->name('v1.domain1-1');
  293. $api->get('domain1-2', function () { return 'hi'; })->name('v1.domain1-2');
  294. $api->get('/prefix1/domain1-1', function () { return 'hi'; })->name('v1.prefix1.domain1-1');
  295. $api->get('prefix1/domain1-2', function () { return 'hi'; })->name('v1.prefix1.domain1-2');
  296. $api->get('/prefix2/domain1-1', function () { return 'hi'; })->name('v1.prefix2.domain1-1');
  297. $api->get('prefix2/domain1-2', function () { return 'hi'; })->name('v1.prefix2.domain1-2');
  298. });
  299. $api->group(['domain' => 'domain2.app.test'], function (Router $api) {
  300. $api->post('/domain2-1', function () { return 'hi'; })->name('v1.domain2-1');
  301. $api->get('domain2-2', function () { return 'hi'; })->name('v1.domain2-2');
  302. $api->get('/prefix1/domain2-1', function () { return 'hi'; })->name('v1.prefix1.domain2-1');
  303. $api->get('prefix1/domain2-2', function () { return 'hi'; })->name('v1.prefix1.domain2-2');
  304. $api->get('/prefix2/domain2-1', function () { return 'hi'; })->name('v1.prefix2.domain2-1');
  305. $api->get('prefix2/domain2-2', function () { return 'hi'; })->name('v1.prefix2.domain2-2');
  306. });
  307. });
  308. $api->version('v2', function (Router $api) {
  309. $api->group(['domain' => 'domain1.app.test'], function (Router $api) {
  310. $api->post('/domain1', function () { return 'hi'; })->name('v2.domain1');
  311. $api->get('/prefix1/domain1', function () { return 'hi'; })->name('v2.prefix1.domain1');
  312. $api->get('/prefix2/domain1', function () { return 'hi'; })->name('v2.prefix2.domain1');
  313. });
  314. $api->group(['domain' => 'domain2.app.test'], function (Router $api) {
  315. $api->post('/domain2', function () { return 'hi'; })->name('v2.domain2');
  316. $api->get('/prefix1/domain2', function () { return 'hi'; })->name('v2.prefix1.domain2');
  317. $api->get('/prefix2/domain2', function () { return 'hi'; })->name('v2.prefix2.domain2');
  318. });
  319. });
  320. }
  321. }