ResponseCallsTest.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. namespace Knuckles\Scribe\Tests\Strategies\Responses;
  3. use Illuminate\Routing\Route;
  4. use Illuminate\Support\Facades\Route as RouteFacade;
  5. use Knuckles\Camel\Extraction\ExtractedEndpointData;
  6. use Knuckles\Camel\Extraction\ResponseCollection;
  7. use Knuckles\Scribe\Extracting\Extractor;
  8. use Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls;
  9. use Knuckles\Scribe\Scribe;
  10. use Knuckles\Scribe\Tests\BaseLaravelTest;
  11. use Knuckles\Scribe\Tests\Fixtures\TestController;
  12. use Knuckles\Scribe\Tools\DocumentationConfig;
  13. use Illuminate\Support\Facades\Route as LaravelRouteFacade;
  14. use Symfony\Component\HttpFoundation\Request;
  15. class ResponseCallsTest extends BaseLaravelTest
  16. {
  17. /** @test */
  18. public function can_call_route_and_fetch_response()
  19. {
  20. $route = LaravelRouteFacade::post('/shouldFetchRouteResponse', [TestController::class, 'shouldFetchRouteResponse']);
  21. $responses = $this->invokeStrategy($route);
  22. $this->assertEquals(200, $responses[0]['status']);
  23. $this->assertArraySubset([
  24. 'id' => 4,
  25. 'name' => 'banana',
  26. 'color' => 'red',
  27. 'weight' => '1 kg',
  28. 'delicious' => true,
  29. ], json_decode($responses[0]['content'], true));
  30. }
  31. /** @test */
  32. public function can_upload_file_parameters_in_response_calls()
  33. {
  34. $route = RouteFacade::post('/withFormDataParams', [TestController::class, 'withFormDataParams']);
  35. /* This doesn't work. It always gives an error, "the file failed to upload". However, uploading files worked when they are extracted params
  36. $endpointData = ExtractedEndpointData::fromRoute($route, [ 'headers' => [ 'accept' => 'application/json' ] ]);
  37. $responses = $this->invokeStrategy($endpointData, settings: [
  38. 'fileParams' => [ 'image' => 'config/scribe.php' ],
  39. 'bodyParams' => [ 'name' => 'cat.jpg' ]
  40. ]);
  41. */
  42. $this->setConfig([
  43. 'strategies.responses' => [
  44. [ResponseCalls::class,
  45. ['only' => 'POST *']
  46. ],
  47. ]
  48. ]);
  49. $parsed = (new Extractor())->processRoute($route);
  50. $responses = $parsed->responses->toArray();
  51. $this->assertCount(1, $responses);
  52. $this->assertArraySubset([
  53. "status" => 200,
  54. "description" => null,
  55. "content" => '{"filename":"scribe.php","filepath":"config","name":"cat.jpg"}',
  56. ], $responses[0]);
  57. }
  58. /** @test */
  59. public function uses_configured_settings_when_calling_route()
  60. {
  61. $route = LaravelRouteFacade::post('/echo/{id}', [TestController::class, 'echoesRequestValues']);
  62. $endpointData = ExtractedEndpointData::fromRoute($route, [
  63. 'auth' => ['headers', 'Authorization', 'Bearer bearerToken'],
  64. 'headers' => [
  65. 'Content-Type' => 'application/json',
  66. 'Accept' => 'application/json',
  67. 'header' => 'headerValue',
  68. ],
  69. ]);
  70. $responses = $this->invokeStrategy($endpointData, settings: [
  71. 'queryParams' => [
  72. 'queryParam' => 'queryValue',
  73. ],
  74. 'bodyParams' => [
  75. 'bodyParam' => 'bodyValue',
  76. ],
  77. ]);
  78. $this->assertEquals(200, $responses[0]['status']);
  79. $responseContent = json_decode($responses[0]['content'], true);
  80. $this->assertEquals('queryValue', $responseContent['queryParam']);
  81. $this->assertEquals('bodyValue', $responseContent['bodyParam']);
  82. $this->assertEquals('headerValue', $responseContent['header']);
  83. $this->assertEquals('Bearer bearerToken', $responseContent['auth']);
  84. }
  85. /** @test */
  86. public function can_override_application_config_during_response_call()
  87. {
  88. $route = LaravelRouteFacade::post('/echoesConfig', [TestController::class, 'echoesConfig']);
  89. $responses = $this->invokeStrategy($route);
  90. $originalValue = json_decode($responses[0]['content'], true)['app.env'];
  91. $now = time();
  92. $responses = $this->invokeStrategy($route, settings: [
  93. 'config' => [
  94. 'app.env' => $now,
  95. ],
  96. ],);
  97. $newValue = json_decode($responses[0]['content'], true)['app.env'];
  98. $this->assertEquals($now, $newValue);
  99. $this->assertNotEquals($originalValue, $newValue);
  100. }
  101. /** @test */
  102. public function calls_beforeResponseCall_hook()
  103. {
  104. Scribe::beforeResponseCall(function (Request $request, ExtractedEndpointData $endpointData) {
  105. $request->headers->set("header", "overridden_".$request->headers->get("header"));
  106. $request->headers->set("Authorization", "overridden_".$request->headers->get("Authorization"));
  107. $request->query->set("queryParam", "overridden_".$request->query->get("queryParam"));
  108. $request->request->set("bodyParam", "overridden_".$endpointData->uri.$request->request->get("bodyParam"));
  109. });
  110. $route = LaravelRouteFacade::post('/echo/{id}', [TestController::class, 'echoesRequestValues']);
  111. $endpointData = ExtractedEndpointData::fromRoute($route, [
  112. 'auth' => ['headers', 'Authorization', 'Bearer bearerToken'],
  113. 'headers' => [
  114. 'Content-Type' => 'application/json',
  115. 'Accept' => 'application/json',
  116. 'header' => 'headerValue',
  117. ],
  118. ]);
  119. $responses = $this->invokeStrategy($endpointData, settings: [
  120. 'queryParams' => [
  121. 'queryParam' => 'queryValue',
  122. ],
  123. 'bodyParams' => [
  124. 'bodyParam' => 'bodyValue',
  125. ],
  126. ]);
  127. $this->assertEquals(200, $responses[0]['status']);
  128. $responseContent = json_decode($responses[0]['content'], true);
  129. $this->assertEquals('overridden_queryValue', $responseContent['queryParam']);
  130. $this->assertEquals('overridden_headerValue', $responseContent['header']);
  131. $this->assertEquals('overridden_Bearer bearerToken', $responseContent['auth']);
  132. $this->assertEquals('overridden_echo/{id}bodyValue', $responseContent['bodyParam']);
  133. Scribe::beforeResponseCall(fn() => null);
  134. }
  135. /** @test */
  136. public function does_not_make_response_call_if_success_response_already_gotten()
  137. {
  138. $route = LaravelRouteFacade::post('/shouldFetchRouteResponse', [TestController::class, 'shouldFetchRouteResponse']);
  139. $endpointData = ExtractedEndpointData::fromRoute($route, [
  140. 'responses' => new ResponseCollection([
  141. [
  142. 'status' => 200,
  143. 'content' => json_encode(['message' => 'LOL']),
  144. ],
  145. ]),
  146. ]);
  147. $responses = $this->invokeStrategy($endpointData);
  148. $this->assertNull($responses);
  149. }
  150. protected function convertRules(array $rules): mixed
  151. {
  152. return Extractor::transformOldRouteRulesIntoNewSettings('responses', $rules, ResponseCalls::class);
  153. }
  154. protected function invokeStrategy(ExtractedEndpointData|Route $route, $settings = []): ?array
  155. {
  156. $strategy = new ResponseCalls(new DocumentationConfig([]));
  157. return $strategy(
  158. $route instanceof ExtractedEndpointData ? $route : ExtractedEndpointData::fromRoute($route), $settings
  159. );
  160. }
  161. }