From e242a7f40ad9c9372e466da0cafd99681da22ac7 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Tue, 1 Aug 2023 13:47:36 +0100 Subject: [PATCH 1/4] Added a failing test --- tests/ReaderTest.php | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/ReaderTest.php b/tests/ReaderTest.php index 589b7cb..6a7530e 100644 --- a/tests/ReaderTest.php +++ b/tests/ReaderTest.php @@ -129,6 +129,64 @@ public function testSymfonyYamlBugHunt() } + public function testForceUniqueOperationIdJSON(){ + $api = \cebe\openapi\Reader::readFromJson(<<assertFalse($api->validate()); + } + + + public function testForceUniqueOperationIdYAML(){ + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertFalse($openapi->validate()); + } + + // TODO test invalid JSON // TODO test invalid YAML } From 4d35dad71f90c241b77702c471ee2ffa7af18431 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Wed, 2 Aug 2023 12:55:07 +0100 Subject: [PATCH 2/4] Updated php fixer to version 3 --- .gitignore | 1 + .php_cs.dist => .php-cs-fixer.dist.php | 2 +- Makefile | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename .php_cs.dist => .php-cs-fixer.dist.php (92%) 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..3594ae9 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 From c83ef0fe523ff5e50fb0503383567a01eb0ceeb2 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Wed, 2 Aug 2023 12:58:46 +0100 Subject: [PATCH 3/4] Added validation to check duplicate operation IDs --- src/json/JsonPointer.php | 10 +++---- src/spec/Paths.php | 16 +++++++++++ tests/ReaderTest.php | 58 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 6 deletions(-) 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/Paths.php b/src/spec/Paths.php index e504a90..7257bd7 100644 --- a/src/spec/Paths.php +++ b/src/spec/Paths.php @@ -46,6 +46,10 @@ class Paths implements SpecObjectInterface, DocumentContextInterface, ArrayAcces * @var JsonPointer|null */ private $_jsonPointer; + /** + * @var string + */ + private $_operationsIds = []; /** @@ -147,6 +151,18 @@ public function validate(): bool if (strpos($key, '/') !== 0) { $this->_errors[] = "Path must begin with /: $key"; } + $operations = $path->getOperations(); + foreach($operations as $operation) { + $id = $operation->operationId; + if(empty($id)) { + continue; + } + if(!empty($this->_operationsIds[$id]) && $this->_operationsIds[$id]) { + $this->_errors[] = "Operation ID '$id', already exist. Operation IDs must be unique."; + $valid = false; + } + $this->_operationsIds[$id] = true; + } } return $valid && empty($this->_errors); } diff --git a/tests/ReaderTest.php b/tests/ReaderTest.php index 6a7530e..e75c89d 100644 --- a/tests/ReaderTest.php +++ b/tests/ReaderTest.php @@ -130,6 +130,7 @@ public function testSymfonyYamlBugHunt() public function testForceUniqueOperationIdJSON(){ + //Duplicate $api = \cebe\openapi\Reader::readFromJson(<<assertFalse($api->validate()); + + //Non duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertTrue($api->validate()); } public function testForceUniqueOperationIdYAML(){ + //Duplicate $openapi = \cebe\openapi\Reader::readFromYaml(<<assertFalse($openapi->validate()); + $this->assertFalse($openapi->validate()); + + //Non Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertTrue($openapi->validate()); } From be4faee7e5fa8aa3e72152f2c649ebe7c983e009 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Fri, 8 Sep 2023 16:30:49 +0100 Subject: [PATCH 4/4] Added more tests for cross path validation --- tests/ReaderTest.php | 121 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/tests/ReaderTest.php b/tests/ReaderTest.php index e75c89d..218e504 100644 --- a/tests/ReaderTest.php +++ b/tests/ReaderTest.php @@ -197,7 +197,80 @@ public function testForceUniqueOperationIdJSON(){ $this->assertTrue($api->validate()); } + //Different Paths + public function testForceUniqueOperationIdInDifferentPathsJSON(){ + //Duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertFalse($api->validate()); + + // Non duplicate + $api = \cebe\openapi\Reader::readFromJson(<<assertTrue($api->validate()); + } + //The same paths public function testForceUniqueOperationIdYAML(){ //Duplicate $openapi = \cebe\openapi\Reader::readFromYaml(<<assertTrue($openapi->validate()); } + //Duplicate Different paths + public function testForceUniqueOperationIdInDifferentPathsYAML(){ + //Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertFalse($openapi->validate()); + + //Non Duplicate + $openapi = \cebe\openapi\Reader::readFromYaml(<<assertTrue($openapi->validate()); + } + // TODO test invalid JSON // TODO test invalid YAML