diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e75081c..4ca4f9dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed +# 4.40.0 (3 February 2024) +## Added +- Correctly list required fields for nested objects in OpenAPI spec (request bodies) [99b71ebf0](https://github.com/knuckleswtf/scribe/commit/99b71ebf058e679c3020779583be4de6b576ba3b) +- Add support for defining Groups and Subgroups as enums [#932](https://github.com/knuckleswtf/scribe/pull/932) + # 4.39.0 (31 December 2024) ## Added -- Correctly list required fields for nested objects in OpenAPI spec [#905](https://github.com/knuckleswtf/scribe/pull/905) +- Correctly list required fields for nested objects in OpenAPI spec (responses) [#905](https://github.com/knuckleswtf/scribe/pull/905) - Cursor pagination support in API responses (`cursorPaginate`/`paginate=cursor`) [#917](https://github.com/knuckleswtf/scribe/pull/917) ## Fixed diff --git a/composer.json b/composer.json index 5fdfb795..5a8393bf 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,8 @@ "phpstan/phpstan": "^2.1.1", "phpunit/phpunit": "^9.0|^10.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0" + "symfony/dom-crawler": "^5.4|^6.0", + "spatie/ray": "^1.41" }, "autoload": { "psr-4": { diff --git a/src/Scribe.php b/src/Scribe.php index 80259669..6f7f51d6 100644 --- a/src/Scribe.php +++ b/src/Scribe.php @@ -9,7 +9,7 @@ class Scribe { - public const VERSION = '4.39.0'; + public const VERSION = '4.40.0'; /** * Specify a callback that will be executed just before a response call is made diff --git a/tests/Unit/OpenAPISpecWriterTest.php b/tests/Unit/OpenAPISpecWriterTest.php index 6b4747bd..eff431ad 100644 --- a/tests/Unit/OpenAPISpecWriterTest.php +++ b/tests/Unit/OpenAPISpecWriterTest.php @@ -863,17 +863,39 @@ public function adds_more_than_two_answers_correctly_using_oneOf() public function adds_enum_values_to_response_properties() { $endpointData = $this->createMockEndpointData([ - 'uri' => '/path', - 'httpMethods' => ['POST'], + 'httpMethods' => ['GEt'], + 'uri' => '/path1', 'responses' => [ [ 'status' => 200, - 'description' => 'This one', - 'content' => '{"status": "one"}', + 'description' => 'List of entities', + 'content' => '{"data":[{"name":"Resource name","uuid":"UUID","primary":true}]}', ], ], 'responseFields' => [ - 'status' => ['enumValues' => ['one', 'two', 'three']], + '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, + ], ], ]); @@ -883,19 +905,100 @@ public function adds_enum_values_to_response_properties() $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 lists_required_properties_in_request_body() + { + $endpointData = $this->createMockEndpointData([ + 'uri' => '/path', + 'httpMethods' => ['POST'], + 'bodyParameters' => [ + 'my_field' => [ + 'name' => 'my_field', + 'description' => '', + 'required' => true, + 'example' => 'abc', + 'type' => 'string', + 'nullable' => false, + ], + 'other_field.nested_field' => [ + 'name' => 'nested_field', + 'description' => '', + 'required' => true, + 'example' => 'abc', + 'type' => 'string', + 'nullable' => false, + ], + ], + ]); + $groups = [$this->createGroup([$endpointData])]; + $results = $this->generate($groups); + + $this->assertArraySubset([ + 'requestBody' => [ 'content' => [ 'application/json' => [ 'schema' => [ + 'type' => 'object', 'properties' => [ - 'status' => [ - 'enum' => ['one', 'two', 'three'], + 'my_field' => [ + 'type' => 'string', + ], + 'other_field' => [ + 'type' => 'object', + 'properties' => [ + 'nested_field' => [ + 'type' => 'string', + ], + ], + 'required' => ['nested_field'], ], ], + 'required' => ['my_field'] ], ], ], ], - ], $results['paths']['/path']['post']['responses']); + ], $results['paths']['/path']['post']); } /** @test */