瀏覽代碼

Refactor + add tests for ResponseFIeld attribute

shalvah 2 年之前
父節點
當前提交
0deae21769

+ 2 - 18
src/Attributes/ResponseFromFile.php

@@ -3,6 +3,7 @@
 namespace Knuckles\Scribe\Attributes;
 
 use Attribute;
+use Knuckles\Scribe\Extracting\Shared\ResponseFileTools;
 
 #[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_FUNCTION | Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
 class ResponseFromFile
@@ -20,24 +21,7 @@ class ResponseFromFile
         return  [
             "status" => $this->status,
             "description" => $this->description,
-            "content" => $this->getFileResponse($this->file, $this->merge)
+            "content" => ResponseFileTools::getResponseContents($this->file, $this->merge)
         ];
     }
-
-    protected function getFileResponse($filePath, array $merge): string
-    {
-        if (!file_exists($filePath)) {
-            if (!file_exists(storage_path($filePath))) {
-                throw new \InvalidArgumentException("@responseFile {$filePath} does not exist");
-            }
-
-            $filePath = storage_path($filePath);
-        }
-
-        $content = file_get_contents($filePath, true);
-        if (!empty($merge)) {
-            $content = json_encode(array_merge(json_decode($content, true), $merge));
-        }
-        return $content;
-    }
 }

+ 36 - 0
src/Extracting/Shared/ResponseFileTools.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace Knuckles\Scribe\Extracting\Shared;
+
+class ResponseFileTools
+{
+    public static function getResponseContents($filePath, array|string|null $merge): string
+    {
+        $content = self::getFileContents($filePath);
+        if (empty($merge)) {
+            return $content;
+        }
+
+        if (is_string($merge)) {
+            $json = str_replace("'", '"', $merge);
+            return json_encode(array_merge(json_decode($content, true), json_decode($json, true)));
+        }
+
+        if (is_array($merge)) {
+            return json_encode(array_merge(json_decode($content, true), $merge));
+        }
+    }
+
+    protected static function getFileContents($filePath): string
+    {
+        if (!file_exists($filePath)) {
+            // Try Laravel storage folder
+            if (!file_exists(storage_path($filePath))) {
+                throw new \InvalidArgumentException("@responseFile {$filePath} does not exist");
+            }
+
+            $filePath = storage_path($filePath);
+        }
+        return file_get_contents($filePath, true);
+    }
+}

+ 0 - 7
src/Extracting/Strategies/GetFieldsFromTagStrategy.php

@@ -3,7 +3,6 @@
 namespace Knuckles\Scribe\Extracting\Strategies;
 
 use Knuckles\Scribe\Extracting\ParamHelpers;
-use Knuckles\Scribe\Extracting\TagStrategyWithFormRequestFallback;
 use Mpociot\Reflection\DocBlock\Tag;
 
 abstract class GetFieldsFromTagStrategy extends TagStrategyWithFormRequestFallback
@@ -12,12 +11,6 @@ abstract class GetFieldsFromTagStrategy extends TagStrategyWithFormRequestFallba
 
     protected string $tagName = "";
 
-    /**
-     * @param Tag[] $tagsOnMethod
-     * @param Tag[] $tagsOnClass
-     *
-     * @return array[]
-     */
     public function getFromTags(array $tagsOnMethod, array $tagsOnClass = []): array
     {
         $fields = [];

+ 1 - 1
src/Extracting/Strategies/Headers/GetFromHeaderTag.php

@@ -3,7 +3,7 @@
 namespace Knuckles\Scribe\Extracting\Strategies\Headers;
 
 use Knuckles\Scribe\Extracting\ParamHelpers;
-use Knuckles\Scribe\Extracting\TagStrategyWithFormRequestFallback;
+use Knuckles\Scribe\Extracting\Strategies\TagStrategyWithFormRequestFallback;
 use Knuckles\Scribe\Tools\Utils;
 use Mpociot\Reflection\DocBlock\Tag;
 

+ 1 - 1
src/Extracting/Strategies/ResponseFields/GetFromResponseFieldAttribute.php

@@ -13,7 +13,7 @@ use Knuckles\Scribe\Extracting\Strategies\PhpAttributeStrategy;
  */
 class GetFromResponseFieldAttribute extends PhpAttributeStrategy
 {
-    protected string $attributeName = ResponseField::class;
+    protected array $attributeNames = [ResponseField::class];
 
     protected function extractFromAttributes(array $attributesOnMethod, array $attributesOnController, ExtractedEndpointData $endpointData): ?array
     {

+ 1 - 1
src/Extracting/Strategies/ResponseFields/GetFromResponseFieldTag.php

@@ -19,7 +19,7 @@ class GetFromResponseFieldTag extends GetFieldsFromTagStrategy
         preg_match('/(.+?)\s+(.+?)\s+([\s\S]*)/', $tagContent, $content);
         if (empty($content)) {
             // This means only name and type were supplied
-            [$name, $type] = preg_split('/\s+/', $tag->getContent());
+            [$name, $type] = preg_split('/\s+/', $tagContent);
             $description = '';
         } else {
             [$_, $name, $type, $description] = $content;

+ 2 - 26
src/Extracting/Strategies/Responses/UseResponseFileTag.php

@@ -4,6 +4,7 @@ namespace Knuckles\Scribe\Extracting\Strategies\Responses;
 
 use Knuckles\Camel\Extraction\ExtractedEndpointData;
 use Knuckles\Scribe\Extracting\RouteDocBlocker;
+use Knuckles\Scribe\Extracting\Shared\ResponseFileTools;
 use Knuckles\Scribe\Extracting\Strategies\Strategy;
 use Knuckles\Scribe\Tools\AnnotationParser as a;
 use Knuckles\Scribe\Tools\Utils;
@@ -38,8 +39,7 @@ class UseResponseFileTag extends Strategy
 
             $status = $attributes['status'] ?: ($status ?: 200);
             $description = $attributes['scenario'] ? "$status, {$attributes['scenario']}" : "$status";
-
-            $content = $this->getResponseContents($filePath, $json);
+            $content = ResponseFileTools::getResponseContents($filePath, $json);
 
             return [
                 'content' => $content,
@@ -50,28 +50,4 @@ class UseResponseFileTag extends Strategy
 
         return $responses;
     }
-
-    protected function getResponseContents($filePath, ?string $json): string
-    {
-        $content = $this->getFileContents($filePath);
-        if ($json) {
-            $json = str_replace("'", '"', $json);
-            $content = json_encode(array_merge(json_decode($content, true), json_decode($json, true)));
-        }
-        return $content;
-    }
-
-    protected function getFileContents($filePath): string
-    {
-        if (!file_exists($filePath)) {
-            // Try Laravel storage folder
-            if (!file_exists(storage_path($filePath))) {
-                throw new \InvalidArgumentException("@responseFile {$filePath} does not exist");
-            }
-
-            $filePath = storage_path($filePath);
-        }
-        return file_get_contents($filePath, true);
-    }
-
 }

+ 6 - 8
src/Extracting/TagStrategyWithFormRequestFallback.php → src/Extracting/Strategies/TagStrategyWithFormRequestFallback.php

@@ -1,19 +1,15 @@
 <?php
 
-namespace Knuckles\Scribe\Extracting;
+namespace Knuckles\Scribe\Extracting\Strategies;
 
-use Illuminate\Foundation\Http\FormRequest as LaravelFormRequest;
-use Dingo\Api\Http\FormRequest as DingoFormRequest;
 use Illuminate\Routing\Route;
 use Knuckles\Camel\Extraction\ExtractedEndpointData;
-use Knuckles\Scribe\Extracting\Strategies\Strategy;
+use Knuckles\Scribe\Extracting\FindsFormRequestForMethod;
+use Knuckles\Scribe\Extracting\RouteDocBlocker;
 use Mpociot\Reflection\DocBlock;
-use ReflectionClass;
-use ReflectionException;
 use ReflectionFunctionAbstract;
-use ReflectionUnionType;
 
-class TagStrategyWithFormRequestFallback extends Strategy
+abstract class TagStrategyWithFormRequestFallback extends Strategy
 {
     use FindsFormRequestForMethod;
 
@@ -39,4 +35,6 @@ class TagStrategyWithFormRequestFallback extends Strategy
         $methodDocBlock = RouteDocBlocker::getDocBlocksFromRoute($route)['method'];
         return $this->getFromTags($methodDocBlock->getTags(), $classTags);
     }
+
+    abstract public function getFromTags(array $tagsOnMethod, array $tagsOnClass = []): array;
 }

+ 0 - 14
tests/Strategies/ResponseFields/GetFromResponseFieldAttributeTest.php

@@ -1,14 +0,0 @@
-<?php
-
-namespace Knuckles\Scribe\Tests\Strategies\ResponseFields;
-
-use Knuckles\Camel\Extraction\ResponseCollection;
-use Knuckles\Scribe\Extracting\Strategies\ResponseFields\GetFromResponseFieldTag;
-use Knuckles\Scribe\Tools\DocumentationConfig;
-use Mpociot\Reflection\DocBlock\Tag;
-use PHPUnit\Framework\TestCase;
-use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
-
-class GetFromResponseFieldAttributeTest extends TestCase
-{
-}

+ 79 - 0
tests/Strategies/ResponseFields/GetFromResponseFieldAttributesTest.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace Knuckles\Scribe\Tests\Strategies\ResponseFields;
+
+use Closure;
+use Knuckles\Camel\Extraction\ExtractedEndpointData;
+use Knuckles\Camel\Extraction\ResponseCollection;
+use Knuckles\Scribe\Attributes\ResponseField;
+use Knuckles\Scribe\Extracting\Strategies\ResponseFields\GetFromResponseFieldAttribute;
+use Knuckles\Scribe\Tools\DocumentationConfig;
+use PHPUnit\Framework\TestCase;
+use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
+use ReflectionClass;
+
+class GetFromResponseFieldAttributesTest extends TestCase
+{
+    use ArraySubsetAsserts;
+
+    /** @test */
+    public function can_fetch_from_responsefield_attribute()
+    {
+        $endpoint = $this->endpoint(function (ExtractedEndpointData $e) {
+            $e->controller = new ReflectionClass(ResponseFieldAttributeTestController::class);
+            $e->method = $e->controller->getMethod('methodWithAttributes');
+            $e->responses = new ResponseCollection([
+                [
+                    'status' => 400,
+                    'content' => json_encode(['id' => 6.4]),
+                ],
+                [
+                    'status' => 200,
+                    'content' => json_encode(['id' => 6]),
+                ],
+                [
+                    'status' => 201,
+                    'content' => json_encode(['id' => 'haha']),
+                ],
+            ]);
+        });
+        $results = $this->fetch($endpoint);
+
+        $this->assertArraySubset([
+            'id' => [
+                'type' => 'integer',
+                'description' => 'The id of the newly created user.',
+            ],
+            'other' => [
+                'type' => 'string',
+                'description' => '',
+            ],
+        ], $results);
+    }
+
+    protected function fetch($endpoint): array
+    {
+        $strategy = new GetFromResponseFieldAttribute(new DocumentationConfig([]));
+        return $strategy($endpoint);
+    }
+
+    protected function endpoint(Closure $configure): ExtractedEndpointData
+    {
+        $endpoint = new class extends ExtractedEndpointData {
+            public function __construct(array $parameters = [])
+            {
+            }
+        };
+        $configure($endpoint);
+        return $endpoint;
+    }
+}
+
+class ResponseFieldAttributeTestController
+{
+    #[ResponseField('id', description: 'The id of the newly created user.')]
+    #[ResponseField('other', 'string')]
+    public function methodWithAttributes()
+    {
+    }
+}

+ 5 - 0
tests/Strategies/ResponseFields/GetFromResponseFieldTagTest.php

@@ -20,6 +20,7 @@ class GetFromResponseFieldTagTest extends TestCase
     {
         $tags = [
             new Tag('responseField', 'id int The id of the newly created user.'),
+            new Tag('responseField', 'other string'),
         ];
         $results = $this->fetch($tags);
 
@@ -28,6 +29,10 @@ class GetFromResponseFieldTagTest extends TestCase
                 'type' => 'integer',
                 'description' => 'The id of the newly created user.',
             ],
+            'other' => [
+                'type' => 'string',
+                'description' => '',
+            ],
         ], $results);
     }