Browse Source

Feature/required fields for nested objects (#905)

* Fixing #903 - required response fields in OpenAPI

- added check for `required` response fields in nested object inspection

* Testcase for `required` on nested objects

---------

Co-authored-by: Peter Krupa <pkrupa@purple-next.com>
Peter Krupa 6 months ago
parent
commit
018cac9d44
2 changed files with 91 additions and 0 deletions
  1. 5 0
      src/Writing/OpenAPISpecWriter.php
  2. 86 0
      tests/Unit/OpenAPISpecWriterTest.php

+ 5 - 0
src/Writing/OpenAPISpecWriter.php

@@ -635,6 +635,11 @@ class OpenAPISpecWriter
                 $schema['items']['properties'] = collect($sample)->mapWithKeys(function ($v, $k) use ($endpoint, $path) {
                     return [$k => $this->generateSchemaForValue($v, $endpoint, "$path.$k")];
                 })->toArray();
+
+                $required = $this->filterRequiredFields($endpoint, array_keys($schema['items']['properties']), $path);
+                if ($required) {
+                    $schema['required'] = $required;
+                }
             }
         }
 

+ 86 - 0
tests/Unit/OpenAPISpecWriterTest.php

@@ -598,6 +598,92 @@ class OpenAPISpecWriterTest extends BaseUnitTest
         ], $results['paths']['/path2']['put']['responses']);
     }
 
+    /** @test */
+    public function adds_required_fields_on_objects_wrapped_in_array()
+    {
+        $endpointData = $this->createMockEndpointData([
+            'httpMethods' => ['GEt'],
+            'uri' => '/path1',
+            'responses' => [
+                [
+                    'status' => 200,
+                    'description' => 'List of entities',
+                    'content' => '{"data":[{"name":"Resource name","uuid":"UUID","primary":true}]}',
+                ],
+            ],
+            'responseFields' => [
+                'data' => [
+                    'name' => 'data',
+                    'type' => 'array',
+                    'description' => 'Data wrapper',
+                ],
+                'data.name' => [
+                    'name' => 'Resource name',
+                    'type' => 'string',
+                    'description' => 'Name of the resource object',
+                    'required' => true,
+                ],
+                'data.uuid' => [
+                    'name' => 'Resource UUID',
+                    'type' => 'string',
+                    'description' => 'Unique ID for the resource',
+                    'required' => true,
+                ],
+                'data.primary' => [
+                    'name' => 'Is primary',
+                    'type' => 'bool',
+                    'description' => 'Is primary resource',
+                    'required' => true,
+                ],
+            ],
+        ]);
+
+        $groups = [$this->createGroup([$endpointData])];
+
+        $results = $this->generate($groups);
+
+        $this->assertArraySubset([
+            '200' => [
+                'description' => 'List of entities',
+                'content' => [
+                    'application/json' => [
+                        'schema' => [
+                            'type' => 'object',
+                            'properties' => [
+                                'data' => [
+                                    'type' => 'array',
+                                    'description' => 'Data wrapper',
+                                    'items' => [
+                                        'type' => 'object',
+                                        'properties' => [
+                                            'name' => [
+                                                'type' => 'string',
+                                                'description' => 'Name of the resource object',
+                                            ],
+                                            'uuid' => [
+                                                'type' => 'string',
+                                                'description' => 'Unique ID for the resource',
+                                            ],
+                                            'primary' => [
+                                                'type' => 'boolean',
+                                                'description' => 'Is primary resource',
+                                            ],
+                                        ],
+                                    ],
+                                    'required' => [
+                                        'name',
+                                        'uuid',
+                                        'primary',
+                                    ]
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ], $results['paths']['/path1']['get']['responses']);
+    }
+
     /** @test */
     public function adds_multiple_responses_correctly_using_oneOf()
     {