GeneratorPluginSystemTest.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. namespace Knuckles\Scribe\Tests\Unit;
  3. use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
  4. use Illuminate\Routing\Route;
  5. use Knuckles\Scribe\Extracting\Generator;
  6. use Knuckles\Scribe\Extracting\Strategies\Strategy;
  7. use Knuckles\Scribe\ScribeServiceProvider;
  8. use Knuckles\Scribe\Tests\Fixtures\TestController;
  9. use Knuckles\Scribe\Tools\DocumentationConfig;
  10. use PHPUnit\Framework\TestCase;
  11. use ReflectionClass;
  12. use ReflectionFunctionAbstract;
  13. class GeneratorPluginSystemTest extends TestCase
  14. {
  15. use ArraySubsetAsserts;
  16. /**
  17. * @var \Knuckles\Scribe\Extracting\Generator
  18. */
  19. protected $generator;
  20. protected function getPackageProviders($app)
  21. {
  22. $providers = [
  23. ScribeServiceProvider::class,
  24. ];
  25. if (class_exists(\Dingo\Api\Provider\LaravelServiceProvider::class)) {
  26. $providers[] = \Dingo\Api\Provider\LaravelServiceProvider::class;
  27. }
  28. return $providers;
  29. }
  30. protected function tearDown(): void
  31. {
  32. EmptyStrategy1::$called = false;
  33. EmptyStrategy2::$called = false;
  34. NotDummyMetadataStrategy::$called = false;
  35. parent::tearDown();
  36. }
  37. /** @test */
  38. public function only_specified_strategies_are_loaded()
  39. {
  40. $config = [
  41. 'strategies' => [
  42. 'metadata' => [NotDummyMetadataStrategy::class],
  43. 'bodyParameters' => [
  44. EmptyStrategy1::class,
  45. ],
  46. 'responses' => [], // Making this empty so the Laravel-dependent strategies are not called
  47. ],
  48. ];
  49. $route = $this->createRoute('GET', '/api/test', 'dummy', true, TestController::class);
  50. $generator = new Generator(new DocumentationConfig($config));
  51. $generator->processRoute($route);
  52. $this->assertTrue(EmptyStrategy1::$called);
  53. $this->assertTrue(NotDummyMetadataStrategy::$called);
  54. $this->assertFalse(EmptyStrategy2::$called);
  55. }
  56. /** @test */
  57. public function responses_from_different_strategies_get_added()
  58. {
  59. $config = [
  60. 'strategies' => [
  61. 'responses' => [DummyResponseStrategy200::class, DummyResponseStrategy400::class],
  62. ],
  63. ];
  64. $route = $this->createRoute('GET', '/api/test', 'dummy', true, TestController::class);
  65. $generator = new Generator(new DocumentationConfig($config));
  66. $parsed = $generator->processRoute($route);
  67. $this->assertTrue($parsed['showresponse']);
  68. $this->assertCount(2, $parsed['responses']);
  69. $first = array_shift($parsed['responses']);
  70. $this->assertTrue(is_array($first));
  71. $this->assertEquals(200, $first['status']);
  72. $this->assertEquals('dummy', $first['content']);
  73. $second = array_shift($parsed['responses']);
  74. $this->assertTrue(is_array($second));
  75. $this->assertEquals(400, $second['status']);
  76. $this->assertEquals('dummy2', $second['content']);
  77. }
  78. /**
  79. * @test
  80. * This is a generalized test, as opposed to the one above for responses only
  81. */
  82. public function combines_results_from_different_strategies_in_same_stage()
  83. {
  84. $config = [
  85. 'strategies' => [
  86. 'metadata' => [PartialDummyMetadataStrategy1::class, PartialDummyMetadataStrategy2::class],
  87. 'responses' => [],
  88. ],
  89. ];
  90. $route = $this->createRoute('GET', '/api/test', 'dummy', true, TestController::class);
  91. $generator = new Generator(new DocumentationConfig($config));
  92. $parsed = $generator->processRoute($route);
  93. $expectedMetadata = [
  94. 'groupName' => 'dummy',
  95. 'groupDescription' => 'dummy',
  96. 'title' => 'dummy',
  97. 'description' => 'dummy',
  98. 'authenticated' => false,
  99. ];
  100. $this->assertArraySubset($expectedMetadata, $parsed['metadata']);
  101. }
  102. /** @test */
  103. public function missing_metadata_is_filled_in()
  104. {
  105. $config = [
  106. 'strategies' => [
  107. 'metadata' => [PartialDummyMetadataStrategy2::class],
  108. 'responses' => [],
  109. ],
  110. ];
  111. $route = $this->createRoute('GET', '/api/test', 'dummy', true, TestController::class);
  112. $generator = new Generator(new DocumentationConfig($config));
  113. $parsed = $generator->processRoute($route);
  114. $expectedMetadata = [
  115. 'groupName' => '',
  116. 'groupDescription' => 'dummy',
  117. 'title' => '',
  118. 'description' => 'dummy',
  119. 'authenticated' => false,
  120. ];
  121. $this->assertArraySubset($expectedMetadata, $parsed['metadata']);
  122. }
  123. /** @test */
  124. public function overwrites_metadata_from_previous_strategies_in_same_stage()
  125. {
  126. $config = [
  127. 'strategies' => [
  128. 'metadata' => [NotDummyMetadataStrategy::class, PartialDummyMetadataStrategy1::class],
  129. 'responses' => [],
  130. ],
  131. ];
  132. $route = $this->createRoute('GET', '/api/test', 'dummy', true, TestController::class);
  133. $generator = new Generator(new DocumentationConfig($config));
  134. $parsed = $generator->processRoute($route);
  135. $expectedMetadata = [
  136. 'groupName' => 'dummy',
  137. 'groupDescription' => 'notdummy',
  138. 'title' => 'dummy',
  139. 'description' => 'dummy',
  140. 'authenticated' => false,
  141. ];
  142. $this->assertArraySubset($expectedMetadata, $parsed['metadata']);
  143. }
  144. public function createRoute(string $httpMethod, string $path, string $controllerMethod, $register = false, $class = TestController::class)
  145. {
  146. return new Route([$httpMethod], $path, ['uses' => $class . "@$controllerMethod"]);
  147. }
  148. }
  149. class EmptyStrategy1 extends Strategy
  150. {
  151. public static $called = false;
  152. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  153. {
  154. static::$called = true;
  155. }
  156. }
  157. class EmptyStrategy2 extends Strategy
  158. {
  159. public static $called = false;
  160. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  161. {
  162. static::$called = true;
  163. }
  164. }
  165. class NotDummyMetadataStrategy extends Strategy
  166. {
  167. public static $called = false;
  168. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  169. {
  170. static::$called = true;
  171. return [
  172. 'groupName' => 'notdummy',
  173. 'groupDescription' => 'notdummy',
  174. 'title' => 'notdummy',
  175. 'description' => 'notdummy',
  176. 'authenticated' => true,
  177. ];
  178. }
  179. }
  180. class PartialDummyMetadataStrategy1 extends Strategy
  181. {
  182. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  183. {
  184. return [
  185. 'groupName' => 'dummy',
  186. 'title' => 'dummy',
  187. 'description' => 'dummy',
  188. 'authenticated' => false,
  189. ];
  190. }
  191. }
  192. class PartialDummyMetadataStrategy2 extends Strategy
  193. {
  194. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  195. {
  196. return [
  197. 'description' => 'dummy',
  198. 'groupDescription' => 'dummy',
  199. ];
  200. }
  201. }
  202. class DummyResponseStrategy200 extends Strategy
  203. {
  204. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  205. {
  206. return [['status' => 200, 'content' => 'dummy']];
  207. }
  208. }
  209. class DummyResponseStrategy400 extends Strategy
  210. {
  211. public function __invoke(Route $route, ReflectionClass $controller, ReflectionFunctionAbstract $method, array $routeRules, array $alreadyExtractedData = [])
  212. {
  213. return [['status' => 400, 'content' => 'dummy2']];
  214. }
  215. }