GetFromLaravelAPITest.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. namespace Knuckles\Scribe\Tests\Strategies\UrlParameters;
  3. use Closure;
  4. use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
  5. use Illuminate\Database\Schema\Blueprint;
  6. use Illuminate\Routing\Router;
  7. use Illuminate\Support\Facades\Schema;
  8. use Knuckles\Camel\Extraction\ExtractedEndpointData;
  9. use Knuckles\Scribe\Extracting\Shared\UrlParamsNormalizer;
  10. use Knuckles\Scribe\Extracting\Strategies\UrlParameters\GetFromLaravelAPI;
  11. use Knuckles\Scribe\Tests\BaseLaravelTest;
  12. use Knuckles\Scribe\Tests\Fixtures\TestController;
  13. use Knuckles\Scribe\Tests\Fixtures\TestUser;
  14. use Knuckles\Scribe\Tools\DocumentationConfig;
  15. class GetFromLaravelAPITest extends BaseLaravelTest
  16. {
  17. use ArraySubsetAsserts;
  18. /** @test */
  19. public function can_infer_type_from_model_binding()
  20. {
  21. // $endpoint = $this->endpointForRoute("users/{id}", TestController::class, 'withInjectedModel');
  22. $endpoint = $this->endpointForRoute("categories/{category}/users/{id}/", TestController::class, 'withInjectedEnumAndModel');
  23. $results = $this->fetch($endpoint);
  24. $this->assertArraySubset([
  25. "name" => "id",
  26. "description" => "The ID of the user.",
  27. "required" => true,
  28. "type" => "integer",
  29. ], $results['id']);
  30. $this->assertArraySubset([
  31. "name" => "category",
  32. "description" => "The category.",
  33. "required" => true,
  34. "type" => "string",
  35. "example" => \Knuckles\Scribe\Tests\Fixtures\Category::cases()[0]->value,
  36. ], $results['category']);
  37. $this->assertIsInt($results['id']['example']);
  38. }
  39. /** @test */
  40. public function can_infer_description_from_url()
  41. {
  42. $endpoint = $this->endpointForRoute("everything/{cat_id}", TestController::class, 'dummy');
  43. $results = $this->fetch($endpoint);
  44. $this->assertArraySubset([
  45. "name" => "cat_id",
  46. "description" => "The ID of the cat.",
  47. "required" => true,
  48. "type" => "string",
  49. ], $results['cat_id']);
  50. $endpoint->route = app(Router::class)->addRoute(['GET'], 'dogs/{id}', ['uses' => [TestController::class, 'dummy']]);;
  51. $endpoint->uri = $endpoint->route->uri;
  52. $results = $this->fetch($endpoint);
  53. $this->assertArraySubset([
  54. "name" => "id",
  55. "description" => "The ID of the dog.",
  56. "required" => true,
  57. "type" => "string",
  58. ], $results['id']);
  59. }
  60. /** @test */
  61. public function can_infer_example_from_wheres()
  62. {
  63. $regex = '/catz\d+-\d/';
  64. $endpoint = $this->endpoint(function (ExtractedEndpointData $e) use ($regex) {
  65. $e->method = new \ReflectionMethod(TestController::class, 'dummy');
  66. $e->route = app(Router::class)->addRoute(['GET'], "everything/{cat_id}", ['uses' => [TestController::class, 'dummy']])
  67. ->where('cat_id', $regex);
  68. $e->uri = UrlParamsNormalizer::normalizeParameterNamesInRouteUri($e->route, $e->method);
  69. });
  70. $results = $this->fetch($endpoint);
  71. $this->assertArraySubset([
  72. "name" => "cat_id",
  73. "description" => "The ID of the cat.",
  74. "required" => true,
  75. "type" => "string",
  76. ], $results['cat_id']);
  77. $this->assertMatchesRegularExpression($regex, $results['cat_id']['example']);
  78. }
  79. /** @test */
  80. public function can_infer_data_from_field_bindings()
  81. {
  82. $endpoint = $this->endpointForRoute("audio/{audio:slug}", TestController::class, 'dummy');
  83. $results = $this->fetch($endpoint);
  84. $this->assertArraySubset([
  85. "name" => "audio_slug",
  86. "description" => "The slug of the audio.",
  87. "required" => true,
  88. "type" => "string",
  89. ], $results['audio_slug']);
  90. Schema::create('test_users', function (Blueprint $table) {
  91. $table->id();
  92. $table->string('name');
  93. });
  94. $user = TestUser::create(['name' => 'Bully Maguire', 'id' => 23]);
  95. $endpoint = $this->endpointForRoute("users/{user:id}", TestController::class, 'withInjectedModel');
  96. $results = $this->fetch($endpoint);
  97. $this->assertArraySubset([
  98. "name" => "user_id",
  99. "description" => "The ID of the user.",
  100. "required" => true,
  101. "type" => "integer",
  102. "example" => $user->id,
  103. ], $results['user_id']);
  104. }
  105. /** @test */
  106. public function can_infer_from_model_even_if_not_bound()
  107. {
  108. $oldNamespace = $this->app->getNamespace();
  109. $reflectedApp = new \ReflectionClass($this->app);
  110. $property = $reflectedApp->getProperty('namespace');
  111. $property->setAccessible(true);
  112. $property->setValue($this->app, "Knuckles\\Scribe\\Tests\\Fixtures\\");
  113. $endpoint = $this->endpointForRoute("test-users/{id}", TestController::class, 'dummy');
  114. $results = $this->fetch($endpoint);
  115. $this->assertArraySubset([
  116. "name" => "id",
  117. "description" => "The ID of the test user.",
  118. "required" => true,
  119. "type" => "integer",
  120. ], $results['id']);
  121. $property->setValue($this->app, $oldNamespace);
  122. }
  123. protected function endpointForRoute($path, $controller, $method): ExtractedEndpointData
  124. {
  125. return $this->endpoint(function (ExtractedEndpointData $e) use ($path, $method, $controller) {
  126. $e->method = new \ReflectionMethod($controller, $method);
  127. $e->route = app(Router::class)->addRoute(['GET'], $path, ['uses' => [$controller, $method]]);
  128. $e->uri = UrlParamsNormalizer::normalizeParameterNamesInRouteUri($e->route, $e->method);
  129. });
  130. }
  131. protected function endpoint(Closure $configure): ExtractedEndpointData
  132. {
  133. $endpoint = new class extends ExtractedEndpointData {
  134. public function __construct(array $parameters = [])
  135. {
  136. }
  137. };
  138. $configure($endpoint);
  139. return $endpoint;
  140. }
  141. protected function fetch($endpoint): array
  142. {
  143. $strategy = new GetFromLaravelAPI(new DocumentationConfig([]));
  144. return $strategy($endpoint, []);
  145. }
  146. }