ResponseCallsTest.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?php
  2. namespace Knuckles\Scribe\Tests\Extracting\Strategies\Responses;
  3. use Dingo\Api\Routing\Router;
  4. use Illuminate\Routing\Route;
  5. use Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls;
  6. use Knuckles\Scribe\ScribeServiceProvider;
  7. use Knuckles\Scribe\Tests\Fixtures\TestController;
  8. use Knuckles\Scribe\Tools\DocumentationConfig;
  9. use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
  10. use Knuckles\Scribe\Tools\Flags;
  11. use Orchestra\Testbench\TestCase;
  12. use Illuminate\Support\Facades\Route as LaravelRouteFacade;
  13. use Dingo\Api\Routing\Router as DingoRouter;
  14. class ResponseCallsTest extends TestCase
  15. {
  16. use ArraySubsetAsserts;
  17. protected function getPackageProviders($app)
  18. {
  19. $providers = [
  20. ScribeServiceProvider::class,
  21. ];
  22. if (class_exists(\Dingo\Api\Provider\LaravelServiceProvider::class)) {
  23. $providers[] = \Dingo\Api\Provider\LaravelServiceProvider::class;
  24. }
  25. return $providers;
  26. }
  27. /** @test */
  28. public function can_call_route_and_fetch_response()
  29. {
  30. $route = LaravelRouteFacade::post('/shouldFetchRouteResponse', [TestController::class, 'shouldFetchRouteResponse']);
  31. $rules = [
  32. 'headers' => [
  33. 'Content-Type' => 'application/json',
  34. 'Accept' => 'application/json',
  35. ],
  36. 'response_calls' => [
  37. 'methods' => ['*'],
  38. ],
  39. ];
  40. $strategy = new ResponseCalls(new DocumentationConfig([]));
  41. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  42. $this->assertEquals(200, $results[0]['status']);
  43. $this->assertArraySubset([
  44. 'id' => 4,
  45. 'name' => 'banana',
  46. 'color' => 'red',
  47. 'weight' => '1 kg',
  48. 'delicious' => true,
  49. ], json_decode($results[0]['content'], true));
  50. }
  51. /** @test */
  52. public function uses_configured_settings_when_calling_route()
  53. {
  54. $route = LaravelRouteFacade::post('/echo/{id}', [TestController::class, 'shouldFetchRouteResponseWithEchoedSettings']);
  55. $rules = [
  56. 'response_calls' => [
  57. 'methods' => ['*'],
  58. 'queryParams' => [
  59. 'queryParam' => 'queryValue',
  60. ],
  61. 'bodyParams' => [
  62. 'bodyParam' => 'bodyValue',
  63. ],
  64. ],
  65. ];
  66. $context = [
  67. 'auth' => 'headers.Authorization.Bearer bearerToken',
  68. 'headers' => [
  69. 'Content-Type' => 'application/json',
  70. 'Accept' => 'application/json',
  71. 'header' => 'value',
  72. ],
  73. ];
  74. $strategy = new ResponseCalls(new DocumentationConfig([]));
  75. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, $context);
  76. $this->assertEquals(200, $results[0]['status']);
  77. $responseContent = json_decode($results[0]['content'], true);
  78. $this->assertEquals('queryValue', $responseContent['queryParam']);
  79. $this->assertEquals('bodyValue', $responseContent['bodyParam']);
  80. $this->assertEquals('value', $responseContent['header']);
  81. $this->assertEquals('Bearer bearerToken', $responseContent['auth']);
  82. }
  83. /** @test */
  84. public function can_override_application_config_during_response_call()
  85. {
  86. $route = LaravelRouteFacade::post('/echoesConfig', [TestController::class, 'echoesConfig']);
  87. $rules = [
  88. 'response_calls' => [
  89. 'methods' => ['*'],
  90. ],
  91. ];
  92. $strategy = new ResponseCalls(new DocumentationConfig([]));
  93. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  94. $originalValue = json_decode($results[0]['content'], true)['app.env'];
  95. $now = time();
  96. $rules = [
  97. 'response_calls' => [
  98. 'methods' => ['*'],
  99. 'config' => [
  100. 'app.env' => $now,
  101. ],
  102. ],
  103. ];
  104. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  105. $newValue = json_decode($results[0]['content'], true)['app.env'];
  106. $this->assertEquals($now, $newValue);
  107. $this->assertNotEquals($originalValue, $newValue);
  108. }
  109. /**
  110. * @test
  111. * @group dingo
  112. */
  113. public function can_call_route_and_fetch_response_with_dingo()
  114. {
  115. $route = $this->registerDingoRoute('post', '/shouldFetchRouteResponse', 'shouldFetchRouteResponse');
  116. $rules = [
  117. 'headers' => [
  118. 'Content-Type' => 'application/json',
  119. 'Accept' => 'application/json',
  120. ],
  121. 'response_calls' => [
  122. 'methods' => ['*'],
  123. ],
  124. ];
  125. $strategy = new ResponseCalls(new DocumentationConfig(['router' => 'dingo']));
  126. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  127. $this->assertEquals(200, $results[0]['status']);
  128. $this->assertArraySubset([
  129. 'id' => 4,
  130. 'name' => 'banana',
  131. 'color' => 'red',
  132. 'weight' => '1 kg',
  133. 'delicious' => true,
  134. ], json_decode($results[0]['content'], true));
  135. }
  136. /**
  137. * @test
  138. * @group dingo
  139. */
  140. public function uses_configured_settings_when_calling_route_with_dingo()
  141. {
  142. $route = $this->registerDingoRoute('post','/echo/{id}', 'shouldFetchRouteResponseWithEchoedSettings');
  143. $rules = [
  144. 'response_calls' => [
  145. 'methods' => ['*'],
  146. 'queryParams' => [
  147. 'queryParam' => 'queryValue',
  148. ],
  149. 'bodyParams' => [
  150. 'bodyParam' => 'bodyValue',
  151. ],
  152. ],
  153. ];
  154. $context = [
  155. 'headers' => [
  156. 'Content-Type' => 'application/json',
  157. 'Accept' => 'application/json',
  158. 'header' => 'value',
  159. ],
  160. ];
  161. $strategy = new ResponseCalls(new DocumentationConfig(['router' => 'dingo']));
  162. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, $context);
  163. $this->assertEquals(200, $results[0]['status']);
  164. $responseContent = json_decode($results[0]['content'], true);
  165. $this->assertEquals('queryValue', $responseContent['queryParam']);
  166. $this->assertEquals('bodyValue', $responseContent['bodyParam']);
  167. $this->assertEquals('value', $responseContent['header']);
  168. }
  169. /**
  170. * @test
  171. * @group dingo
  172. */
  173. public function can_override_application_config_during_response_call_with_dingo()
  174. {
  175. $route = $this->registerDingoRoute('post','/echoesConfig', 'echoesConfig');
  176. $rules = [
  177. 'response_calls' => [
  178. 'methods' => ['*'],
  179. ],
  180. ];
  181. $strategy = new ResponseCalls(new DocumentationConfig(['router' => 'dingo']));
  182. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  183. $originalValue = json_decode($results[0]['content'], true)['app.env'];
  184. $now = time();
  185. $rules = [
  186. 'response_calls' => [
  187. 'methods' => ['*'],
  188. 'config' => [
  189. 'app.env' => $now,
  190. ],
  191. ],
  192. ];
  193. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, []);
  194. $newValue = json_decode($results[0]['content'], true)['app.env'];
  195. $this->assertEquals($now, $newValue);
  196. $this->assertNotEquals($originalValue, $newValue);
  197. }
  198. /** @test */
  199. public function does_not_make_response_call_if_success_response_already_gotten()
  200. {
  201. $route = LaravelRouteFacade::post('/shouldFetchRouteResponse', [TestController::class, 'shouldFetchRouteResponse']);
  202. $rules = [
  203. 'headers' => [
  204. 'Content-Type' => 'application/json',
  205. 'Accept' => 'application/json',
  206. ],
  207. 'response_calls' => [
  208. 'methods' => ['*'],
  209. ],
  210. ];
  211. $context = [
  212. 'responses' => [
  213. [
  214. 'status' => 200,
  215. 'content' => json_encode(['message' => 'LOL']),
  216. ]
  217. ]
  218. ];
  219. $strategy = new ResponseCalls(new DocumentationConfig([]));
  220. $results = $strategy->makeResponseCallIfEnabledAndNoSuccessResponses($route, $rules, $context);
  221. $this->assertNull($results);
  222. }
  223. public function registerDingoRoute(string $httpMethod, string $path, string $controllerMethod)
  224. {
  225. $desiredRoute = null;
  226. /** @var Router $api */
  227. $api = app(Router::class);
  228. $api->version('v1', function (Router $api) use ($controllerMethod, $path, $httpMethod, &$desiredRoute) {
  229. $desiredRoute = $api->$httpMethod($path, [TestController::class, $controllerMethod]);
  230. });
  231. $routes = app(\Dingo\Api\Routing\Router::class)->getRoutes('v1');
  232. /*
  233. * Doing this bc we want an instance of Dingo\Api\Routing\Route, not Illuminate\Routing\Route, which the method above returns
  234. */
  235. return collect($routes)
  236. ->first(function (Route $route) use ($desiredRoute) {
  237. return $route->uri() === $desiredRoute->uri();
  238. });
  239. }
  240. }