From 32c9a420078c2facffbf4900d7cd6569d11e879f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Mon, 8 Sep 2025 12:29:08 +0200 Subject: [PATCH] Added ErrorMessage schema --- phpstan-baseline.neon | 6 --- .../config/services/rest_schema.yaml | 4 ++ src/contracts/BaseRestWebTestCase.php | 27 ++++------- .../Value/EndpointRequestDefinition.php | 19 +++++++- src/lib/Schema/ErrorSchemaProvider.php | 47 +++++++++++++++++++ 5 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 src/lib/Schema/ErrorSchemaProvider.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 0b9fc26..ce14e58 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsString\(\) with string will always evaluate to true\.$#' - identifier: staticMethod.alreadyNarrowedType - count: 1 - path: src/contracts/BaseRestWebTestCase.php - - message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Test\\\\Rest\\\\Request\\\\Value\\\\EndpointRequestDefinition'' and Ibexa\\Contracts\\Test\\Rest\\Request\\Value\\EndpointRequestDefinition will always evaluate to true\.$#' identifier: staticMethod.alreadyNarrowedType diff --git a/src/bundle/Resources/config/services/rest_schema.yaml b/src/bundle/Resources/config/services/rest_schema.yaml index 1fe414e..4b1b50c 100644 --- a/src/bundle/Resources/config/services/rest_schema.yaml +++ b/src/bundle/Resources/config/services/rest_schema.yaml @@ -42,5 +42,9 @@ services: $uriRetriever: '@ibexa.test.rest.json_schema.uri_retriever' $schemas: !tagged_iterator ibexa.test.rest.schema_provider + Ibexa\Test\Rest\Schema\ErrorSchemaProvider: + tags: + - { name: ibexa.test.rest.schema_provider } + ibexa.test.rest.json_schema.uri_retriever: class: JsonSchema\Uri\UriRetriever diff --git a/src/contracts/BaseRestWebTestCase.php b/src/contracts/BaseRestWebTestCase.php index b23ce2d..bdb5473 100644 --- a/src/contracts/BaseRestWebTestCase.php +++ b/src/contracts/BaseRestWebTestCase.php @@ -45,19 +45,13 @@ public function testEndpoint(EndpointRequestDefinition $endpointDefinition): voi if (null === $expectedStatusCode) { self::assertResponseIsSuccessful(); } else { - $actualStatusCode = $response->getStatusCode(); - self::assertSame( - $actualStatusCode, - $expectedStatusCode, - "Expected HTTP $expectedStatusCode, got HTTP $actualStatusCode status code" - ); + self::assertResponseStatusCodeSame($expectedStatusCode); } $content = (string)$response->getContent(); $this->assertResponseIsValid( $content, - $endpointDefinition->getExpectedResourceType(), - $endpointDefinition->extractFormatFromAcceptHeader() + $endpointDefinition, ); $snapshotName = $endpointDefinition->getSnapshotName(); @@ -112,15 +106,12 @@ protected function performRequest(EndpointRequestDefinition $endpointDefinition) return $this->client->getResponse(); } - /** - * @phpstan-param 'xml'|'json' $format - */ protected function assertResponseIsValid( string $response, - ?string $resourceType, - string $format + EndpointRequestDefinition $endpointDefinition ): void { - self::assertIsString($response); + $resourceType = $endpointDefinition->getExpectedResourceType(); + $format = $endpointDefinition->extractFormatFromAcceptHeader(); if (null !== $resourceType) { self::assertStringContainsString($resourceType, $response); @@ -129,7 +120,8 @@ protected function assertResponseIsValid( self::generateMediaTypeString($resourceType, $format) ); - $this->validateAgainstSchema($response, $resourceType, $format); + $schemaLocation = $endpointDefinition->getSchemaLocation() ?? $this->getSchemaFileBasePath($resourceType, $format); + $this->validateAgainstSchema($response, $resourceType, $format, $schemaLocation); } else { self::assertEmpty($response, "The response for '$format' format is not empty"); } @@ -173,11 +165,12 @@ protected static function generateMediaTypeString(string $typeString, ?string $f private function validateAgainstSchema( string $response, string $resourceType, - string $format + string $format, + string $schemaLocation ): void { try { $validator = $this->getSchemaValidator($format); - $validator->validate($response, $this->getSchemaFileBasePath($resourceType, $format)); + $validator->validate($response, $schemaLocation); } catch (\Throwable $e) { self::fail( sprintf( diff --git a/src/contracts/Request/Value/EndpointRequestDefinition.php b/src/contracts/Request/Value/EndpointRequestDefinition.php index 5a18b72..0b35a9c 100644 --- a/src/contracts/Request/Value/EndpointRequestDefinition.php +++ b/src/contracts/Request/Value/EndpointRequestDefinition.php @@ -30,6 +30,8 @@ final class EndpointRequestDefinition implements Stringable private ?string $name; + private ?string $schemaLocation = null; + /** * Snapshot name or path relative to Snapshot directory defined by overriding * \Ibexa\Contracts\Test\Rest\BaseRestWebTestCase::getSnapshotDirectory. @@ -54,7 +56,8 @@ public function __construct( ?InputPayload $payload = null, ?string $name = null, ?string $snapshotName = null, - ?int $expectedStatusCode = null + ?int $expectedStatusCode = null, + ?string $schemaLocation = null ) { $this->method = $method; $this->uri = $uri; @@ -65,6 +68,7 @@ public function __construct( $this->name = $name; $this->snapshotName = $snapshotName; $this->expectedStatusCode = $expectedStatusCode; + $this->schemaLocation = $schemaLocation; } public function getMethod(): string @@ -131,6 +135,11 @@ public function getName(): ?string return $this->name; } + public function getSchemaLocation(): ?string + { + return $this->schemaLocation; + } + /** * @return 'xml'|'json' */ @@ -183,6 +192,14 @@ public function withSnapshotName(?string $snapshotName): self return $endpointDefinition; } + public function withSchemaLocation(?string $schemaLocation): self + { + $endpointDefinition = clone $this; + $endpointDefinition->schemaLocation = $schemaLocation; + + return $endpointDefinition; + } + public function withExpectedStatusCode(?int $expectedStatusCode): self { $endpointDefinition = clone $this; diff --git a/src/lib/Schema/ErrorSchemaProvider.php b/src/lib/Schema/ErrorSchemaProvider.php new file mode 100644 index 0000000..0eaf61d --- /dev/null +++ b/src/lib/Schema/ErrorSchemaProvider.php @@ -0,0 +1,47 @@ + (object)[ + 'type' => 'object', + 'properties' => [ + 'ErrorMessage' => [ + 'type' => 'object', + 'properties' => [ + '_media-type' => [ + 'type' => 'string', + ], + 'errorCode' => [ + 'type' => 'integer', + ], + 'errorMessage' => [ + 'type' => 'string', + ], + 'errorDescription' => [ + 'type' => 'string', + ], + ], + 'required' => [ + '_media-type', + 'errorCode', + 'errorMessage', + 'errorDescription', + ], + ], + ], + 'required' => ['ErrorMessage'], + ]; + } +}