ExtractedEndpointDataTest.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. namespace Knuckles\Scribe\Tests\Unit;
  3. use Illuminate\Routing\Route as LaravelRoute;
  4. use Illuminate\Support\Facades\Route;
  5. use Knuckles\Camel\Extraction\ExtractedEndpointData;
  6. use Knuckles\Scribe\Matching\RouteMatcher;
  7. use Knuckles\Scribe\Scribe;
  8. use Knuckles\Scribe\Tests\BaseLaravelTest;
  9. use Knuckles\Scribe\Tests\Fixtures\TestController;
  10. class ExtractedEndpointDataTest extends BaseLaravelTest
  11. {
  12. /** @test */
  13. public function normalizes_resource_url_params()
  14. {
  15. Route::apiResource('things', TestController::class)->only('show');
  16. $route = $this->getRoute(['prefixes' => '*']);
  17. $this->assertEquals('things/{thing}', $this->originalUri($route));
  18. $this->assertEquals('things/{id}', $this->expectedUri($route));
  19. Route::apiResource('things.otherthings', TestController::class)->only('destroy');
  20. $route = $this->getRoute(['prefixes' => '*/otherthings/*']);
  21. $this->assertEquals('things/{thing}/otherthings/{otherthing}', $this->originalUri($route));
  22. $this->assertEquals('things/{thing_id}/otherthings/{id}', $this->expectedUri($route));
  23. }
  24. /** @test */
  25. public function allows_user_specified_normalization()
  26. {
  27. Scribe::normalizeEndpointUrlUsing(function (string $url, LaravelRoute $route) {
  28. if ($url == 'things/{thing}') return 'things/{the_id_of_the_thing}';
  29. if ($route->named('things.otherthings.destroy')) return 'things/{thing-id}/otherthings/{other_thing-id}';
  30. });
  31. Route::apiResource('things', TestController::class)->only('show');
  32. $route = $this->getRoute(['prefixes' => '*']);
  33. $this->assertEquals('things/{thing}', $this->originalUri($route));
  34. $this->assertEquals('things/{the_id_of_the_thing}', $this->expectedUri($route));
  35. Route::apiResource('things.otherthings', TestController::class)->only('destroy');
  36. $route = $this->getRoute(['prefixes' => '*/otherthings/*']);
  37. $this->assertEquals('things/{thing}/otherthings/{otherthing}', $this->originalUri($route));
  38. $this->assertEquals('things/{thing-id}/otherthings/{other_thing-id}', $this->expectedUri($route));
  39. Scribe::normalizeEndpointUrlUsing(null);
  40. }
  41. /** @test */
  42. public function allows_user_specified_normalization_fallback_to_default()
  43. {
  44. Scribe::normalizeEndpointUrlUsing(function (string $url, LaravelRoute $route,
  45. \ReflectionFunctionAbstract $method, ?\ReflectionClass $controller, callable $default) {
  46. if ($route->named('things.otherthings.destroy')) return 'things/{thing-id}/otherthings/{other_thing-id}';
  47. return $default();
  48. });
  49. Route::apiResource('things', TestController::class)->only('show');
  50. $route = $this->getRoute(['prefixes' => '*']);
  51. $this->assertEquals('things/{thing}', $this->originalUri($route));
  52. $this->assertEquals('things/{id}', $this->expectedUri($route));
  53. Route::apiResource('things.otherthings', TestController::class)->only('destroy');
  54. $route = $this->getRoute(['prefixes' => '*/otherthings/*']);
  55. $this->assertEquals('things/{thing}/otherthings/{otherthing}', $this->originalUri($route));
  56. $this->assertEquals('things/{thing-id}/otherthings/{other_thing-id}', $this->expectedUri($route));
  57. Scribe::normalizeEndpointUrlUsing(null);
  58. }
  59. /** @test */
  60. public function normalizes_resource_url_params_from_underscores_to_hyphens()
  61. {
  62. Route::apiResource('audio-things', TestController::class)->only('show');
  63. $route = $this->getRoute(['prefixes' => '*']);
  64. $this->assertEquals('audio-things/{audio_thing}', $this->originalUri($route));
  65. $this->assertEquals('audio-things/{id}', $this->expectedUri($route));
  66. Route::apiResource('big-users.audio-things.things', TestController::class)->only('store');
  67. $route = $this->getRoute(['prefixes' => '*big-users*']);
  68. $this->assertEquals('big-users/{big_user}/audio-things/{audio_thing}/things', $this->originalUri($route));
  69. $this->assertEquals('big-users/{big_user_id}/audio-things/{audio_thing_id}/things', $this->expectedUri($route));
  70. }
  71. /** @test */
  72. public function normalizes_nonresource_url_params_with_inline_bindings()
  73. {
  74. Route::get('things/{thing:slug}', [TestController::class, 'show']);
  75. $route = $this->getRoute(['prefixes' => '*']);
  76. $this->assertEquals('things/{thing}', $this->originalUri($route));
  77. $this->assertEquals('things/{thing_slug}', $this->expectedUri($route));
  78. }
  79. protected function expectedUri(LaravelRoute $route): string
  80. {
  81. return $this->endpoint($route)->uri;
  82. }
  83. protected function originalUri(LaravelRoute $route): string
  84. {
  85. return $route->uri;
  86. }
  87. protected function endpoint(LaravelRoute $route): ExtractedEndpointData
  88. {
  89. return new ExtractedEndpointData([
  90. 'route' => $route,
  91. 'uri' => $route->uri,
  92. 'httpMethods' => $route->methods,
  93. 'method' => new \ReflectionFunction('dump'), // Just so we don't have null
  94. ]);
  95. }
  96. protected function getRoute(array $matchRules): LaravelRoute
  97. {
  98. $routeRules[0]['match'] = array_merge($matchRules, ['domains' => '*']);
  99. $matchedRoutes = (new RouteMatcher)->getRoutes($routeRules);
  100. $this->assertCount(1, $matchedRoutes);
  101. return $matchedRoutes[0]->getRoute();
  102. }
  103. }