diff --git a/.gitignore b/.gitignore index c86af6f..fa1d02a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /node_modules /.php_cs.cache +/.php-cs-fixer.cache /.phpunit.result.cache php-cs-fixer.phar diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 92% rename from .php_cs.dist rename to .php-cs-fixer.dist.php index 704f437..f3585f2 100644 --- a/.php_cs.dist +++ b/.php-cs-fixer.dist.php @@ -1,6 +1,6 @@ setRules([ '@PSR2' => true, 'array_syntax' => ['syntax' => 'short'], diff --git a/Makefile b/Makefile index ee99b2a..b4fae49 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ check-style: php-cs-fixer.phar fix-style: php-cs-fixer.phar $(DOCKER_PHP) vendor/bin/indent --tabs composer.json - $(DOCKER_PHP) vendor/bin/indent --spaces .php_cs.dist + $(DOCKER_PHP) vendor/bin/indent --spaces .php-cs-fixer.dist.php $(DOCKER_PHP) ./php-cs-fixer.phar fix src/ --diff install: composer.lock yarn.lock diff --git a/src/ReferenceContext.php b/src/ReferenceContext.php index bde0a96..514174e 100644 --- a/src/ReferenceContext.php +++ b/src/ReferenceContext.php @@ -23,11 +23,11 @@ class ReferenceContext * The result will be a single API description file with references * inside of the file structure. */ - const RESOLVE_MODE_INLINE = 'inline'; + public const RESOLVE_MODE_INLINE = 'inline'; /** * resolve all references, except recursive ones. */ - const RESOLVE_MODE_ALL = 'all'; + public const RESOLVE_MODE_ALL = 'all'; /** * @var bool whether to throw UnresolvableReferenceException in case a reference can not @@ -103,7 +103,7 @@ private function buildUri($parts) $host = $parts['host'] ?? ''; $port = !empty($parts['port']) ? ':' . $parts['port'] : ''; $user = $parts['user'] ?? ''; - $pass = !empty($parts['pass']) ? ':' . $parts['pass'] : ''; + $pass = !empty($parts['pass']) ? ':' . $parts['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = $parts['path'] ?? ''; $query = !empty($parts['query']) ? '?' . $parts['query'] : ''; diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 1de429b..7a8812e 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -348,6 +348,35 @@ protected function validateUrl(string $property) } } + + protected function deleteProperty($key, $name = null, $value = null): void + { + if(is_array($this->$key) && $name) { + $this->_properties[$key] = $this->_removeKey($this->$key, $name, $value); + } else { + $this->_properties = $this->_removeKey($this->_properties, $key); + } + } + + private function _removeKey(array $arrayData, String $name, $value = null): array + { + if(!empty($arrayData[$name])) { + $properties = $arrayData; + unset($properties[$name]); + return $properties; + } + foreach($arrayData as $key => $val) { + if($name === $val) { + unset($arrayData[$key]); + } elseif($val instanceof self && !empty($val->$name) && $val->$name === $value) { + unset($arrayData[$key]); + } elseif($val instanceof self && !empty($val->$name) && is_array($val->$name)) { + unset($arrayData[$key]); + } + } + return $arrayData; + } + public function __get($name) { if (isset($this->_properties[$name])) { @@ -525,4 +554,13 @@ public function getExtensions(): array } return $extensions; } + + /** + * Remove a property or an attribute + * @param string $name name of property to be removed + */ + public function removeProperty($name) + { + $this->deleteProperty($name); + } } diff --git a/src/json/JsonPointer.php b/src/json/JsonPointer.php index 0e1f75e..3121e08 100644 --- a/src/json/JsonPointer.php +++ b/src/json/JsonPointer.php @@ -107,11 +107,11 @@ public function evaluate($jsonDocument) foreach ($this->getPath() as $part) { if (is_array($currentReference)) { -// if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { -// throw new NonexistentJsonPointerReferenceException( -// "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." -// ); -// } + // if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { + // throw new NonexistentJsonPointerReferenceException( + // "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." + // ); + // } if ($part === '-' || !array_key_exists($part, $currentReference)) { throw new NonexistentJsonPointerReferenceException( "Failed to evaluate pointer '$this->_pointer'. Array has no member $part at path '$currentPath'." diff --git a/src/spec/Components.php b/src/spec/Components.php index c7e7dc1..44088e4 100644 --- a/src/spec/Components.php +++ b/src/spec/Components.php @@ -31,6 +31,46 @@ */ class Components extends SpecBaseObject { + /** + * @param string $name schema name + */ + public function removeSchema(string $name): void + { + $this->deleteProperty('schemas', $name); + } + + /** + * @param string $name parameter name + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', $name); + } + + /** + * @param string $name response name + */ + public function removeResponse(string $name): void + { + $this->deleteProperty('responses', $name); + } + + /** + * @param string $name securityScheme name + */ + public function removeSecuityScheme(string $name): void + { + $this->deleteProperty('securitySchemes', $name); + } + + /** + * @param string $name request body name + */ + public function removeRequestBody(string $name): void + { + $this->deleteProperty('requestBodies', $name); + } + /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Encoding.php b/src/spec/Encoding.php index 865f560..f4448f0 100644 --- a/src/spec/Encoding.php +++ b/src/spec/Encoding.php @@ -23,7 +23,6 @@ */ class Encoding extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Link.php b/src/spec/Link.php index 9d21c2a..a39c521 100644 --- a/src/spec/Link.php +++ b/src/spec/Link.php @@ -48,4 +48,12 @@ protected function performValidation() $this->addError('Link: operationId and operationRef are mutually exclusive.'); } } + + /** + * @param string $name parameter name + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', $name); + } } diff --git a/src/spec/MediaType.php b/src/spec/MediaType.php index 326f8c5..af5e6d6 100644 --- a/src/spec/MediaType.php +++ b/src/spec/MediaType.php @@ -72,6 +72,22 @@ public function __construct(array $data) } } + /** + * @param string $name example name + */ + public function removeExample(string $name): void + { + $this->deleteProperty('examples', $name); + } + + /** + * @param string $name example name + */ + public function removeEncoding(string $name): void + { + $this->deleteProperty('encoding', $name); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. */ diff --git a/src/spec/OAuthFlow.php b/src/spec/OAuthFlow.php index a32536d..88a5321 100644 --- a/src/spec/OAuthFlow.php +++ b/src/spec/OAuthFlow.php @@ -21,7 +21,6 @@ */ class OAuthFlow extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ @@ -35,6 +34,14 @@ protected function attributes(): array ]; } + /** + * @param string $name scope's name + */ + public function removeScope(string $name): void + { + $this->deleteProperty('scopes', $name); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. * diff --git a/src/spec/OpenApi.php b/src/spec/OpenApi.php index 29d38b3..0f7c05b 100644 --- a/src/spec/OpenApi.php +++ b/src/spec/OpenApi.php @@ -44,6 +44,30 @@ protected function attributes(): array ]; } + /** + * @param string $name name of security attribute requirement + */ + public function removeSecurity(string $name): void + { + $this->deleteProperty('security', $name); + } + + /** + * @param string $name tag name + */ + public function removeTag(string $name): void + { + $this->deleteProperty('tags', $name); + } + + /** + * @param string $url server's url value + */ + public function removeServer(string $url): void + { + $this->deleteProperty('servers', 'url', $url); + } + /** * @return array array of attributes default values. */ diff --git a/src/spec/Operation.php b/src/spec/Operation.php index b052532..295da21 100644 --- a/src/spec/Operation.php +++ b/src/spec/Operation.php @@ -29,7 +29,6 @@ */ class Operation extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ @@ -58,6 +57,39 @@ protected function attributeDefaults(): array ]; } + /** + * @param string $name tag name + */ + public function removeTag(string $name): void + { + $this->deleteProperty('tags', $name); + } + + /** + * @param string $name parameter's property key + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', 'name', $name); + } + + /** + * @param string $name name of security requirement + */ + public function removeSecurity(string $name): void + { + $this->deleteProperty('security', $name); + } + + /** + * @param string $name server's property key + */ + public function removeServer(string $name): void + { + $this->deleteProperty('servers', 'url', $name); + } + + /** * Perform validation on this object, check data against OpenAPI Specification rules. * diff --git a/src/spec/PathItem.php b/src/spec/PathItem.php index 4b2debc..f0f2337 100644 --- a/src/spec/PathItem.php +++ b/src/spec/PathItem.php @@ -215,4 +215,30 @@ public function setDocumentContext(SpecObjectInterface $baseDocument, JsonPointe $this->_ref->setDocumentContext($baseDocument, $jsonPointer->append('$ref')); } } + + /** + * @param string $name parameter's property key + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', 'name', $name); + } + + /** + * @param string $name server's url + */ + public function removeServer(string $name): void + { + $this->deleteProperty('servers', 'url', $name); + } + + /** + * @param string $httpVerb is http verb you wish to delete. eg: get, post, etc + * @param string $operationId is unique identify of Operation + */ + public function removeOperation(string $httpVerb, $operationId): void + { + $this->deleteProperty($httpVerb, 'operationId', $operationId); + } + } diff --git a/src/spec/Reference.php b/src/spec/Reference.php index cda612a..2f919a6 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -154,7 +154,7 @@ public function setContext(ReferenceContext $context) /** * @return ReferenceContext */ - public function getContext() : ?ReferenceContext + public function getContext(): ?ReferenceContext { return $this->_context; } diff --git a/src/spec/Response.php b/src/spec/Response.php index 459ad14..27721ac 100644 --- a/src/spec/Response.php +++ b/src/spec/Response.php @@ -34,6 +34,30 @@ protected function attributes(): array ]; } + /** + * @param string $name headers' name + */ + public function removeHeader(string $name): void + { + $this->deleteProperty('headers', $name); + } + + /** + * @param string $operationId headers' operationId + */ + public function removeLinkByOperationId(string $operationId): void + { + $this->deleteProperty('links', 'operationId', $operationId); + } + + /** + * @param string $operationRef link's operationRef + */ + public function removeLinkByoperationRef(string $operationRef): void + { + $this->deleteProperty('links', 'operationRef', $operationRef); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. */ diff --git a/src/spec/Type.php b/src/spec/Type.php index 9861000..0926caf 100644 --- a/src/spec/Type.php +++ b/src/spec/Type.php @@ -14,13 +14,13 @@ */ class Type { - const ANY = 'any'; - const INTEGER = 'integer'; - const NUMBER = 'number'; - const STRING = 'string'; - const BOOLEAN = 'boolean'; - const OBJECT = 'object'; - const ARRAY = 'array'; + public const ANY = 'any'; + public const INTEGER = 'integer'; + public const NUMBER = 'number'; + public const STRING = 'string'; + public const BOOLEAN = 'boolean'; + public const OBJECT = 'object'; + public const ARRAY = 'array'; /** * Indicate whether a type is a scalar type, i.e. not an array or object. diff --git a/tests/spec/ComponentsTest.php b/tests/spec/ComponentsTest.php index 6418c34..e41e4e2 100644 --- a/tests/spec/ComponentsTest.php +++ b/tests/spec/ComponentsTest.php @@ -8,10 +8,11 @@ */ class ComponentsTest extends \PHPUnit\Framework\TestCase { - public function testRead() - { - /** @var $components Components */ - $components = Reader::readFromYaml(<<<'YAML' + public function testRead() + { + /** @var $components Components */ + $components = Reader::readFromYaml( + <<<'YAML' schemas: GeneralError: type: object @@ -78,48 +79,252 @@ public function testRead() scopes: write:pets: modify pets in your account read:pets: read your pets -YAML - , Components::class); - - $result = $components->validate(); - $this->assertEquals([], $components->getErrors()); - $this->assertTrue($result); - - $this->assertAllInstanceOf(\cebe\openapi\spec\Schema::class, $components->schemas); - $this->assertCount(3, $components->schemas); - $this->assertArrayHasKey('GeneralError', $components->schemas); - $this->assertArrayHasKey('Category', $components->schemas); - $this->assertArrayHasKey('Tag', $components->schemas); - $this->assertAllInstanceOf(\cebe\openapi\spec\Response::class, $components->responses); - $this->assertCount(3, $components->responses); - $this->assertArrayHasKey('NotFound', $components->responses); - $this->assertArrayHasKey('IllegalInput', $components->responses); - $this->assertArrayHasKey('GeneralError', $components->responses); - $this->assertAllInstanceOf(\cebe\openapi\spec\Parameter::class, $components->parameters); - $this->assertCount(2, $components->parameters); - $this->assertArrayHasKey('skipParam', $components->parameters); - $this->assertArrayHasKey('limitParam', $components->parameters); - $this->assertAllInstanceOf(\cebe\openapi\spec\Example::class, $components->examples); - $this->assertCount(0, $components->examples); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\RequestBody::class, $components->requestBodies); - $this->assertCount(0, $components->requestBodies); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\Header::class, $components->headers); - $this->assertCount(0, $components->headers); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\SecurityScheme::class, $components->securitySchemes); - $this->assertCount(2, $components->securitySchemes); - $this->assertArrayHasKey('api_key', $components->securitySchemes); - $this->assertArrayHasKey('petstore_auth', $components->securitySchemes); - $this->assertAllInstanceOf(\cebe\openapi\spec\Link::class, $components->links); - $this->assertCount(0, $components->links); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\Callback::class, $components->callbacks); - $this->assertCount(0, $components->callbacks); // TODO - } +YAML, + Components::class + ); + + $result = $components->validate(); + $this->assertEquals([], $components->getErrors()); + $this->assertTrue($result); - public function assertAllInstanceOf($className, $array) - { - foreach($array as $k => $v) { - $this->assertInstanceOf($className, $v, "Asserting that item with key '$k' is instance of $className"); - } + $this->assertAllInstanceOf(\cebe\openapi\spec\Schema::class, $components->schemas); + $this->assertCount(3, $components->schemas); + $this->assertArrayHasKey('GeneralError', $components->schemas); + $this->assertArrayHasKey('Category', $components->schemas); + $this->assertArrayHasKey('Tag', $components->schemas); + $this->assertAllInstanceOf(\cebe\openapi\spec\Response::class, $components->responses); + $this->assertCount(3, $components->responses); + $this->assertArrayHasKey('NotFound', $components->responses); + $this->assertArrayHasKey('IllegalInput', $components->responses); + $this->assertArrayHasKey('GeneralError', $components->responses); + $this->assertAllInstanceOf(\cebe\openapi\spec\Parameter::class, $components->parameters); + $this->assertCount(2, $components->parameters); + $this->assertArrayHasKey('skipParam', $components->parameters); + $this->assertArrayHasKey('limitParam', $components->parameters); + $this->assertAllInstanceOf(\cebe\openapi\spec\Example::class, $components->examples); + $this->assertCount(0, $components->examples); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\RequestBody::class, $components->requestBodies); + $this->assertCount(0, $components->requestBodies); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\Header::class, $components->headers); + $this->assertCount(0, $components->headers); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\SecurityScheme::class, $components->securitySchemes); + $this->assertCount(2, $components->securitySchemes); + $this->assertArrayHasKey('api_key', $components->securitySchemes); + $this->assertArrayHasKey('petstore_auth', $components->securitySchemes); + $this->assertAllInstanceOf(\cebe\openapi\spec\Link::class, $components->links); + $this->assertCount(0, $components->links); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\Callback::class, $components->callbacks); + $this->assertCount(0, $components->callbacks); // TODO + } + + public function assertAllInstanceOf($className, $array) + { + foreach ($array as $k => $v) { + $this->assertInstanceOf($className, $v, "Asserting that item with key '$k' is instance of $className"); } + } + + /** + * Test Delete a named schema + */ + public function testDeleteSchema() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->schemas), 3); + $this->assertTrue(!empty($components->schemas['GeneralError'])); + + $components->removeSchema('GeneralError'); + $this->assertEquals(count($components->schemas), 2); + $this->assertTrue(empty($components->schemas['GeneralError'])); + + $components->removeSchema('Tag'); + $this->assertEquals(count($components->schemas), 1); + $this->assertTrue(empty($components->schemas['Tag'])); + } + + + /** + * Test Delete a named parameter + */ + public function testDeleteParameter() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->parameters), 2); + $this->assertTrue(!empty($components->parameters['skipParam'])); + + $components->removeParameter('skipParam'); + $this->assertEquals(count($components->parameters), 1); + $this->assertTrue(empty($components->parameters['skipParam'])); + + $components->removeParameter('limitParam'); + $this->assertEquals(count($components->parameters), 0); + $this->assertTrue(empty($components->parameters['limitParam'])); + } + + /** + * Test Delete a named response + */ + public function testDeleteResponse() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->responses), 3); + $this->assertTrue(!empty($components->responses['NotFound'])); + + $components->removeResponse('NotFound'); + $this->assertEquals(count($components->responses), 2); + $this->assertTrue(empty($components->responses['NotFound'])); + + $components->removeResponse('GeneralError'); + $this->assertEquals(count($components->responses), 1); + $this->assertTrue(empty($components->responses['GeneralError'])); + } + + /** + * Test Delete a named request body + */ + public function testDeleteRequestBodies() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->requestBodies), 3); + $this->assertTrue(!empty($components->requestBodies['req1'])); + + $components->removeRequestBody('req1'); + $this->assertEquals(count($components->requestBodies), 2); + $this->assertTrue(empty($components->requestBodies['req1'])); + + $components->removeRequestBody('req2'); + $this->assertEquals(count($components->requestBodies), 1); + $this->assertTrue(empty($components->requestBodies['req2'])); + } + + /** + * Test Delete a named security scheme + */ + public function testDeletesecuritySchemes() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->securitySchemes), 2); + $this->assertTrue(!empty($components->securitySchemes['api_key'])); + + $components->removeSecuityScheme('api_key'); + $this->assertEquals(count($components->securitySchemes), 1); + $this->assertTrue(empty($components->securitySchemes['api_key'])); + + } + + protected function componentData(): Components + { + $components = Reader::readFromYaml( + <<<'YAML' + schemas: + GeneralError: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + parameters: + skipParam: + name: skip + in: query + description: number of items to skip + required: true + schema: + type: integer + format: int32 + limitParam: + name: limit + in: query + description: max records to return + required: true + schema: + type: integer + format: int32 + responses: + NotFound: + description: Entity not found. + IllegalInput: + description: Illegal input for operation. + GeneralError: + description: General Error + content: + application/json: + schema: + $ref: '#/components/schemas/GeneralError' + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: http://example.org/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + requestBodies: + req1: + description: 'Request one' + required: true + content: + application/vnd.api+json: + schema: + type: object + properties: + data: + type: array + + req2: + description: 'Request two' + required: true + content: + application/vnd.api+json: + schema: + type: object + properties: + data: + type: array + + req3: + description: 'Request three' + required: true + content: + application/vnd.api+json: + schema: + type: object + YAML, + Components::class + ); + + $result = $components->validate(); + $this->assertEquals([], $components->getErrors()); + $this->assertTrue($result); -} \ No newline at end of file + return $components; + } +} diff --git a/tests/spec/HeaderTest.php b/tests/spec/HeaderTest.php index eeced27..0977236 100644 --- a/tests/spec/HeaderTest.php +++ b/tests/spec/HeaderTest.php @@ -14,6 +14,7 @@ public function testRead() $header = Reader::readFromJson(<<assertEquals('The number of allowed requests in the current period', $header->description); $this->assertInstanceOf(\cebe\openapi\spec\Schema::class, $header->schema); $this->assertEquals('integer', $header->schema->type); + + $this->assertEquals('json', $header->style); + $header->removeProperty('style'); + $this->assertTrue(empty($header->style)); } } diff --git a/tests/spec/InfoTest.php b/tests/spec/InfoTest.php index 932e5e0..b82afaa 100644 --- a/tests/spec/InfoTest.php +++ b/tests/spec/InfoTest.php @@ -46,6 +46,10 @@ public function testRead() $this->assertInstanceOf(License::class, $info->license); $this->assertEquals('Apache 2.0', $info->license->name); $this->assertEquals('https://www.apache.org/licenses/LICENSE-2.0.html', $info->license->url); + + $this->assertNotNull($info->license); + $info->removeProperty('license'); + $this->assertTrue(empty($info->license)); } public function testReadInvalid() diff --git a/tests/spec/LinkTest.php b/tests/spec/LinkTest.php index ea373b6..9866f87 100644 --- a/tests/spec/LinkTest.php +++ b/tests/spec/LinkTest.php @@ -30,6 +30,14 @@ public function testRead() $this->assertEquals(['userId' => 'test.path.id'], $link->parameters); $this->assertEquals(null, $link->requestBody); $this->assertEquals(null, $link->server); + + $this->assertNotNull($link->parameters); + $link->removeParameter('userId'); + $this->assertTrue(empty($link->parameters['userId'])); + + $this->assertNotNull($link->parameters); + $link->removeProperty('parameters'); + $this->assertTrue(empty($link->parameters)); } public function testValidateBothOperationIdAndOperationRef() diff --git a/tests/spec/MediaTypeTest.php b/tests/spec/MediaTypeTest.php index 125e721..2a3f082 100644 --- a/tests/spec/MediaTypeTest.php +++ b/tests/spec/MediaTypeTest.php @@ -71,6 +71,10 @@ public function testRead() ]; $this->assertEquals($expectedCat, $mediaType->examples['cat']->value); + $this->assertNotNull($mediaType->examples); + $mediaType->removeExample('dog'); + $this->assertTrue(empty($mediaType->examples['dog'])); + } public function testCreateionFromObjects() diff --git a/tests/spec/OpenApiTest.php b/tests/spec/OpenApiTest.php index 20b568e..82fd7b3 100644 --- a/tests/spec/OpenApiTest.php +++ b/tests/spec/OpenApiTest.php @@ -79,6 +79,12 @@ public function testReadPetStore() // externalDocs $this->assertNull($openapi->externalDocs); + + $this->assertEquals(1, count($openapi->servers)); + $openapi->removeServer('http://petstore.swagger.io/v1'); + $this->assertEquals(1, count($openapi->servers)); + //Default only + $this->assertEquals('/', $openapi->servers[0]->url); } public function assertAllInstanceOf($className, $array) diff --git a/tests/spec/OperationTest.php b/tests/spec/OperationTest.php index 6e30566..fbb1352 100644 --- a/tests/spec/OperationTest.php +++ b/tests/spec/OperationTest.php @@ -53,6 +53,8 @@ public function testRead() - petstore_auth: - write:pets - read:pets +servers: +- url: https://example.com externalDocs: description: Find more info here url: https://example.com @@ -90,5 +92,25 @@ public function testRead() // deprecated Default value is false. $this->assertFalse($operation->deprecated); + + $this->assertEquals(count($operation->tags), 1); + $operation->removeTag('pet'); + $this->assertEquals(count($operation->tags), 0); + + $this->assertTrue(!empty($operation->operationId)); + $operation->removeProperty('operationId'); + $this->assertTrue(empty($operation->operationId)); + + $this->assertEquals(count($operation->parameters), 1); + $operation->removeParameter('petId'); + $this->assertEquals(count($operation->parameters), 0); + + $this->assertEquals(count($operation->servers), 1); + $operation->removeServer('https://example.com'); + $this->assertEquals(count($operation->servers), 0); + + $this->assertEquals(count($operation->security), 1); + $operation->removeSecurity('petstore_auth'); + $this->assertEquals(count($operation->security), 0); } } diff --git a/tests/spec/PathTest.php b/tests/spec/PathTest.php index 6c46e4b..5b747a7 100644 --- a/tests/spec/PathTest.php +++ b/tests/spec/PathTest.php @@ -192,4 +192,30 @@ public function testPathItemReference() $this->assertEquals('A bar', $barPath->get->responses['200']->description); $this->assertEquals('non-existing resource', $barPath->get->responses['404']->description); } + + public function testPathItemRemoveProperties() + { + $file = __DIR__ . '/data/paths/path-item-test.yaml'; + /** @var $openapi OpenApi */ + $openapi = Reader::readFromYamlFile($file, \cebe\openapi\spec\OpenApi::class, true); + + $this->assertTrue($openapi->validate()); + $barPath = $openapi->paths['/bar']; + + $this->assertCount(2, $barPath->getOperations()); + $this->assertInstanceOf(Operation::class, $barPath->get); + $this->assertEquals('getBar', $barPath->get->operationId); + + $this->assertEquals(count($barPath->parameters), 1); + $barPath->removeParameter('id'); + $this->assertEquals(count($barPath->parameters), 0); + + $barPath->removeOperation('get', 'getBar'); + $this->assertCount(1, $barPath->getOperations()); + + $this->assertInstanceOf(Operation::class, $barPath->post); + $this->assertEquals('createBar', $barPath->post->operationId); + $barPath->removeOperation('post', 'createBar'); + $this->assertEmpty($barPath->getOperations()); + } } diff --git a/tests/spec/ResponseTest.php b/tests/spec/ResponseTest.php index d11b8e2..9aca9f3 100644 --- a/tests/spec/ResponseTest.php +++ b/tests/spec/ResponseTest.php @@ -68,6 +68,20 @@ public function testResponses() /** @var $responses Responses */ $responses = Reader::readFromYaml(<<<'YAML' '200': + headers: + X-RateLimit-Limit: + schema: + type: integer + description: Request limit per hour. + X-RateLimit-Remaining: + schema: + type: integer + description: The number of requests left for the time window. + links: + GetUserByUserId: + operationId: getUser + GetUserByUserRef: + operationRef: '/paths/1/get' description: a pet to be returned content: application/json: @@ -121,6 +135,20 @@ public function testResponses() $this->assertInstanceOf(Response::class, $response); } $this->assertEquals([200, 'default'], $keys); + + //Test Remove headers + $response = $responses['200']; + $this->assertEquals(count($response->headers), 2); + $response->removeHeader('X-RateLimit-Limit'); + $this->assertEquals(count($response->headers), 1); + + //Test Remove links + $this->assertEquals(count($response->links), 2); + $response->removeLinkByOperationId('getUser'); + $this->assertEquals(count($response->links), 1); + + $response->removeLinkByoperationRef('/paths/1/get'); + $this->assertEquals(count($response->links), 0); } public function testResponseCodes() diff --git a/tests/spec/data/paths/path-item-test.yaml b/tests/spec/data/paths/path-item-test.yaml new file mode 100644 index 0000000..6a93299 --- /dev/null +++ b/tests/spec/data/paths/path-item-test.yaml @@ -0,0 +1,33 @@ +openapi: 3.0.2 +info: + title: My API + version: 1.0.0 +x-extension-1: Extension1 +x-extension-2: Extension2 +X-EXTENSION: Invalid because of Uppercase X- +xyz-extension: invalid extension +paths: + /bar: + parameters: + - name: id + in: path + description: ID of the item. + required: true + get: + operationId: getBar + responses: + '200': + $ref: 'openapi.yaml#/components/responses/Bar' + post: + operationId: createBar + responses: + '200': + $ref: 'openapi.yaml#/components/responses/Bar' +components: + responses: + Bar: + description: A bar + content: + application/json: + schema: { type: object } + \ No newline at end of file