diff --git a/.github/actions/setup-php-composer/action.yml b/.github/actions/setup-php-composer/action.yml
index 39cf403..e91d9b1 100644
--- a/.github/actions/setup-php-composer/action.yml
+++ b/.github/actions/setup-php-composer/action.yml
@@ -5,7 +5,7 @@ inputs:
php-version:
description: 'PHP version to use'
required: false
- default: '8.3'
+ default: '8.4'
coverage:
description: 'Coverage driver to use (none, xdebug, pcov)'
required: false
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index b3d8e08..13af43a 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -14,10 +14,10 @@ jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
- fail-fast: true
+ fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
- php: [8.3, 8.4, 8.5]
+ php: [8.4, 8.5]
stability: [prefer-lowest, prefer-stable]
name: PHP${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
diff --git a/README.md b/README.md
index cf7c604..7e92f9a 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ A modern, fluent builder for [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0)
## Requirements
-- PHP 8.3+
+- PHP 8.4+
## Installation
diff --git a/composer.json b/composer.json
index 6a39d87..fe5f565 100644
--- a/composer.json
+++ b/composer.json
@@ -20,19 +20,22 @@
}
],
"require": {
- "php": "^8.3",
+ "php": "^8.4",
"ext-json": "*",
"cortexphp/json-schema": "^1.1",
"opis/json-schema": "^2.4"
},
"require-dev": {
- "pestphp/pest": "^4.1.4",
- "pestphp/pest-plugin-type-coverage": "^4.0.3",
+ "pestphp/pest": "^5.0",
+ "pestphp/pest-plugin-mutate": "^5.0.1",
+ "pestphp/pest-plugin-phpstan": "^5.0",
+ "pestphp/pest-plugin-rector": "^5.0",
+ "pestphp/pest-plugin-type-coverage": "^5.0",
"phpstan/phpstan": "^2.1.32",
"phpstan/phpstan-strict-rules": "^2.0",
"rector/rector": "^2.2",
"symfony/yaml": "^6.0 || ^7.0",
- "symplify/easy-coding-standard": "13.2.3"
+ "symplify/easy-coding-standard": "~13.1.0"
},
"suggest": {
"symfony/yaml": "Required for OpenApi::toYaml() output (^6.0 || ^7.0)."
@@ -51,7 +54,7 @@
]
},
"scripts": {
- "test": "pest --no-coverage",
+ "test": "pest --parallel",
"ecs": "ecs check --fix",
"ecs:check": "ecs check",
"rector": "rector process",
diff --git a/docs/openapi/installation.mdx b/docs/openapi/installation.mdx
index c471221..fbf0d92 100644
--- a/docs/openapi/installation.mdx
+++ b/docs/openapi/installation.mdx
@@ -6,7 +6,7 @@ icon: 'terminal'
## Requirements
-- PHP 8.3+
+- PHP 8.4+
## Installation
diff --git a/docs/openapi/introduction.mdx b/docs/openapi/introduction.mdx
index 206da65..97b562f 100644
--- a/docs/openapi/introduction.mdx
+++ b/docs/openapi/introduction.mdx
@@ -66,7 +66,7 @@ OpenAPI 3.1 aligns fully with **JSON Schema 2020-12**, which means every schema
title="Type Safety"
icon="shield"
>
- Built with PHP 8.3+ strict types, backed enums, and named constructors. PHPStan level 10 clean with 100% type coverage.
+ Built with PHP 8.4+ strict types, backed enums, and named constructors. PHPStan level 10 clean with 100% type coverage.
@@ -130,7 +130,7 @@ echo $doc->toJson(JSON_PRETTY_PRINT);
```
-This package requires PHP 8.3 or higher. `symfony/yaml` is an optional runtime dependency — only needed if you call `toYaml()`.
+This package requires PHP 8.4 or higher. `symfony/yaml` is an optional runtime dependency — only needed if you call `toYaml()`.
## How It Relates to cortexphp/json-schema
diff --git a/ecs.php b/ecs.php
index 49dd243..f3e2bd1 100644
--- a/ecs.php
+++ b/ecs.php
@@ -33,7 +33,7 @@
cleanCode: true,
)
->withPhpCsFixerSets(
- php83Migration: true,
+ php84Migration: true,
)
->withRules([
NotOperatorWithSuccessorSpaceFixer::class,
diff --git a/phpstan.dist.neon b/phpstan.dist.neon
index 2d71067..c6ff3f2 100644
--- a/phpstan.dist.neon
+++ b/phpstan.dist.neon
@@ -1,11 +1,11 @@
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
+ - vendor/pestphp/pest-plugin-phpstan/extension.neon
parameters:
level: 10
paths:
- src
- stubFiles:
- - tests/phpstan/pest-expectations.stub
+ - tests
tmpDir: .phpstan-cache
checkBenevolentUnionTypes: true
diff --git a/rector.php b/rector.php
index 9e47c24..2dd2e5a 100644
--- a/rector.php
+++ b/rector.php
@@ -3,6 +3,7 @@
declare(strict_types=1);
use Rector\Config\RectorConfig;
+use Pest\Rector\Set\PestSetList;
use Rector\CodeQuality\Rector\Catch_\ThrowWithPreviousExceptionRector;
return RectorConfig::configure()
@@ -15,7 +16,12 @@
importDocBlockNames: false,
removeUnusedImports: true,
)
- ->withPhpSets()
+ ->withPhpSets(
+ php84: true,
+ )
+ ->withSets([
+ PestSetList::CODING_STYLE,
+ ])
->withPreparedSets(
deadCode: true,
codeQuality: true,
diff --git a/src/Concerns/BuildsArray.php b/src/Concerns/BuildsArray.php
index 4bb6493..381230b 100644
--- a/src/Concerns/BuildsArray.php
+++ b/src/Concerns/BuildsArray.php
@@ -47,12 +47,12 @@ protected function buildArray(array $fields, array $alwaysInclude = []): array
}
if ($this instanceof HasExtensionsInterface) {
- foreach ($this->getExtensions() as $extensionKey => $extensionValue) {
- $output[$extensionKey] = $extensionValue;
+ foreach ($this->getExtensions() as $extensionKey => $extensionValue) { // @phpstan-ignore foreach.nonIterable
+ $output[$extensionKey] = $extensionValue; // @phpstan-ignore offsetAccess.invalidOffset
}
}
- return $output;
+ return $output; // @phpstan-ignore return.type
}
private function unwrapValue(mixed $value): mixed
diff --git a/src/OpenApi.php b/src/OpenApi.php
index 43de68b..5320230 100644
--- a/src/OpenApi.php
+++ b/src/OpenApi.php
@@ -275,7 +275,7 @@ public function validate(): void
return;
}
- $formatted = (new ErrorFormatter())->format($error);
+ $formatted = new ErrorFormatter()->format($error);
throw new ValidationException(
'OpenAPI document failed meta-schema validation: ' . json_encode($formatted, JSON_UNESCAPED_SLASHES),
diff --git a/tests/Expectations.php b/tests/Expectations.php
index 501f0c5..3de7e13 100644
--- a/tests/Expectations.php
+++ b/tests/Expectations.php
@@ -3,19 +3,59 @@
declare(strict_types=1);
use Cortex\OpenApi\OpenApi;
+use PHPUnit\Framework\Assert;
use Cortex\OpenApi\Exceptions\ValidationException;
/**
- * Custom Pest expectations for OpenAPI meta-schema validation.
- * Method signatures for IDE/static analysis: tests/phpstan/pest-expectations.stub
- *
+ * @return array
+ */
+function expectArray(mixed $value): array
+{
+ expect($value)->toBeArray();
+
+ if (! is_array($value)) {
+ Assert::fail('Expected array.');
+ }
+
+ return $value;
+}
+
+/**
+ * @param array $keys
+ */
+function keyIndex(array $keys, string $key): int
+{
+ $index = array_search($key, $keys, true);
+ expect($index)->toBeInt();
+
+ if (! is_int($index)) {
+ Assert::fail("Expected key [{$key}] to exist.");
+ }
+
+ return $index;
+}
+
+function assertOpenApiValidationPasses(OpenApi $openApi): void
+{
+ try {
+ $openApi->validate();
+ } catch (ValidationException $validationException) {
+ Assert::fail(
+ 'Expected OpenAPI document to pass validation: ' . $validationException->getMessage(),
+ );
+ }
+
+ Assert::assertInstanceOf(OpenApi::class, $openApi);
+}
+
+/**
* @param array> $expectedErrors
*/
function assertOpenApiValidationErrors(OpenApi $openApi, array $expectedErrors): void
{
try {
$openApi->validate();
- test()->fail('Expected ValidationException');
+ Assert::fail('Expected ValidationException');
} catch (ValidationException $validationException) {
foreach ($expectedErrors as $pointer => $messages) {
expect($validationException->errors())->toHaveKey($pointer);
@@ -26,42 +66,9 @@ function assertOpenApiValidationErrors(OpenApi $openApi, array $expectedErrors):
}
}
-expect()->extend('toFailOpenApiValidation', function (array $expectedErrors): mixed {
- if (! $this->value instanceof OpenApi) {
- test()->fail('Expected an OpenApi instance.');
- }
-
- assertOpenApiValidationErrors($this->value, $expectedErrors);
-
- return $this;
-});
-
-expect()->extend('toFailOpenApiValidationAt', function (string $pointer, string $message): mixed {
- if (! $this->value instanceof OpenApi) {
- test()->fail('Expected an OpenApi instance.');
- }
-
- assertOpenApiValidationErrors($this->value, [
+function assertOpenApiValidationFailsAt(OpenApi $openApi, string $pointer, string $message): void
+{
+ assertOpenApiValidationErrors($openApi, [
$pointer => [$message],
]);
-
- return $this;
-});
-
-expect()->extend('toPassOpenApiValidation', function (): mixed {
- if (! $this->value instanceof OpenApi) {
- test()->fail('Expected an OpenApi instance.');
- }
-
- try {
- $this->value->validate();
- } catch (ValidationException $validationException) {
- test()->fail(
- 'Expected OpenAPI document to pass validation: ' . $validationException->getMessage(),
- );
- }
-
- expect($this->value)->toBeInstanceOf(OpenApi::class);
-
- return $this;
-});
+}
diff --git a/tests/Pest.php b/tests/Pest.php
index 5802c47..cbe5884 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -4,4 +4,6 @@
namespace Cortex\OpenApi\Tests;
-uses(TestCase::class)->in('Unit');
+pest()
+ ->extend(TestCase::class)
+ ->in('Unit');
diff --git a/tests/Unit/Concerns/BuildsArrayTest.php b/tests/Unit/Concerns/BuildsArrayTest.php
index af193cf..13732f4 100644
--- a/tests/Unit/Concerns/BuildsArrayTest.php
+++ b/tests/Unit/Concerns/BuildsArrayTest.php
@@ -55,7 +55,7 @@ public function assemble(array $fields): array
}
it('drops null fields', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'title' => 'X',
'version' => null,
]);
@@ -66,7 +66,7 @@ public function assemble(array $fields): array
});
it('drops empty arrays', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'title' => 'X',
'tags' => [],
]);
@@ -77,7 +77,7 @@ public function assemble(array $fields): array
});
it('unwraps a Serializable child', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'info' => new BuildsArraySerializableFixture(),
]);
@@ -89,7 +89,7 @@ public function assemble(array $fields): array
});
it('unwraps a list of Serializable children preserving list semantics', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'tags' => [
new BuildsArraySerializableFixture(),
new BuildsArraySerializableFixture(),
@@ -109,7 +109,7 @@ public function assemble(array $fields): array
});
it('unwraps an associative array of Serializable children preserving keys', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'paths' => [
'/users' => new BuildsArraySerializableFixture(),
'/pets' => new BuildsArraySerializableFixture(),
@@ -143,7 +143,7 @@ public function assemble(array $fields): array
});
it('preserves explicit false values', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'deprecated' => false,
]);
@@ -153,7 +153,7 @@ public function assemble(array $fields): array
});
it('preserves explicit zero values', function (): void {
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'minimum' => 0,
]);
@@ -181,10 +181,10 @@ public function assemble(array $fields): array
// Reference: stand-alone toArray() would include both $schema URI and title.
$standalone = $stringSchema->toArray();
- expect($standalone)->toHaveKey('$schema');
- expect($standalone)->toHaveKey('title', 'IgnoredTitle');
+ expect($standalone)->toHaveKey('$schema')
+ ->toHaveKey('title', 'IgnoredTitle');
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'schema' => $stringSchema,
]);
@@ -202,7 +202,7 @@ public function assemble(array $fields): array
expect($objectSchema->getTitle())->toBe('consults')
->and($objectSchema->getInitialTitle())->toBe('Consult');
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'schema' => $objectSchema,
]);
@@ -211,8 +211,8 @@ public function assemble(array $fields): array
'type' => 'object',
'title' => 'consults',
],
- ]);
- expect($out['schema'])->not->toHaveKey('$schema');
+ ])
+ ->and($out['schema'])->not->toHaveKey('$schema');
});
it('keeps a JsonSchema title set on a schema that had no constructor title', function (): void {
@@ -221,7 +221,7 @@ public function assemble(array $fields): array
expect($stringSchema->getTitle())->toBe('IsoDateTime')
->and($stringSchema->getInitialTitle())->toBeNull();
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'schema' => $stringSchema,
]);
@@ -236,7 +236,7 @@ public function assemble(array $fields): array
it('strips a JsonSchema title that merely restates the constructor argument', function (): void {
$stringSchema = Schema::string('IsoDateTime')->title('IsoDateTime');
- $out = (new BuildsArrayFixture())->assemble([
+ $out = new BuildsArrayFixture()->assemble([
'schema' => $stringSchema,
]);
diff --git a/tests/Unit/Concerns/HasExtensionsTest.php b/tests/Unit/Concerns/HasExtensionsTest.php
index 9c020ea..349c7ef 100644
--- a/tests/Unit/Concerns/HasExtensionsTest.php
+++ b/tests/Unit/Concerns/HasExtensionsTest.php
@@ -6,9 +6,6 @@
covers(HasExtensions::class);
-/**
- * Fixture consumer used purely to exercise the HasExtensions trait.
- */
final class HasExtensionsFixture
{
use HasExtensions;
@@ -65,5 +62,5 @@ final class HasExtensionsFixture
});
it('rejects an empty key', function (): void {
- (new HasExtensionsFixture())->x('');
+ new HasExtensionsFixture()->x('');
})->throws(InvalidArgumentException::class);
diff --git a/tests/Unit/IntegrationTest.php b/tests/Unit/IntegrationTest.php
index e307c7e..77d019a 100644
--- a/tests/Unit/IntegrationTest.php
+++ b/tests/Unit/IntegrationTest.php
@@ -131,14 +131,32 @@ function buildPetstore(): OpenApi
$openApi->validate();
$arr = $openApi->toArray();
-
- expect($arr['openapi'])->toBe('3.1.0');
- expect($arr['info']['title'])->toBe('Swagger Petstore');
- expect($arr['x-api-id'])->toBe('petstore-1');
- expect($arr['paths']['/pets']['get']['operationId'])->toBe('listPets');
- expect($arr['paths']['/pets']['post']['callbacks']['onPetCreate'])->toHaveKey('{$request.body#/webhookUrl}');
- expect($arr['webhooks']['pet.deleted']['post']['operationId'])->toBe('petDeletedWebhook');
- expect($arr['components']['securitySchemes']['OAuth2']['type'])->toBe('oauth2');
+ $info = expectArray($arr['info']);
+ $paths = expectArray($arr['paths']);
+ $pets = expectArray($paths['/pets']);
+ $get = expectArray($pets['get']);
+ $post = expectArray($pets['post']);
+ $callbacks = expectArray($post['callbacks']);
+ $webhooks = expectArray($arr['webhooks']);
+ $petDeleted = expectArray($webhooks['pet.deleted']);
+ $petDeletedPost = expectArray($petDeleted['post']);
+ $components = expectArray($arr['components']);
+ $securitySchemes = expectArray($components['securitySchemes']);
+ $oauth2 = expectArray($securitySchemes['OAuth2']);
+
+ expect($arr['openapi'])->toBe('3.1.0')
+ ->and($info['title'])
+ ->toBe('Swagger Petstore')
+ ->and($arr['x-api-id'])
+ ->toBe('petstore-1')
+ ->and($get['operationId'])
+ ->toBe('listPets')
+ ->and($callbacks['onPetCreate'])
+ ->toHaveKey('{$request.body#/webhookUrl}')
+ ->and($petDeletedPost['operationId'])
+ ->toBe('petDeletedWebhook')
+ ->and($oauth2['type'])
+ ->toBe('oauth2');
});
it('round-trips through JSON encoding', function (): void {
@@ -171,16 +189,22 @@ function buildPetstore(): OpenApi
),
);
- $inline = $openApi->toArray()['paths']['/foo']['get']['responses']['200']['content']['application/json']['schema'];
-
- expect($inline)->not->toHaveKey('$schema');
- expect($inline)->not->toHaveKey('title');
- expect($inline)->toBe([
- 'type' => 'object',
- 'properties' => [
- 'bar' => [
- 'type' => 'string',
+ $paths = expectArray($openApi->toArray()['paths']);
+ $foo = expectArray($paths['/foo']);
+ $get = expectArray($foo['get']);
+ $responses = expectArray($get['responses']);
+ $ok = expectArray($responses['200']);
+ $content = expectArray($ok['content']);
+ $json = expectArray($content['application/json']);
+ $inline = $json['schema'];
+
+ expect($inline)->not->toHaveKey('$schema')->not->toHaveKey('title')
+ ->toBe([
+ 'type' => 'object',
+ 'properties' => [
+ 'bar' => [
+ 'type' => 'string',
+ ],
],
- ],
- ]);
+ ]);
});
diff --git a/tests/Unit/Objects/ComponentsTest.php b/tests/Unit/Objects/ComponentsTest.php
index fa1b1e2..d62fcd8 100644
--- a/tests/Unit/Objects/ComponentsTest.php
+++ b/tests/Unit/Objects/ComponentsTest.php
@@ -21,7 +21,8 @@
covers(Components::class);
it('emits nothing by default', function (): void {
- expect(Components::create()->toArray())->toBe([]);
+ expect(Components::create()->toArray())
+ ->toBeEmpty();
});
it('registers schemas', function (): void {
diff --git a/tests/Unit/Objects/ExampleTest.php b/tests/Unit/Objects/ExampleTest.php
index 8ce7296..952fb30 100644
--- a/tests/Unit/Objects/ExampleTest.php
+++ b/tests/Unit/Objects/ExampleTest.php
@@ -7,7 +7,8 @@
covers(Example::class);
it('emits an empty array when no fields are set', function (): void {
- expect(Example::create()->toArray())->toBe([]);
+ expect(Example::create()->toArray())
+ ->toBeEmpty();
});
it('emits every field when set', function (): void {
@@ -52,5 +53,6 @@
$example->clearValue();
- expect($example->toArray())->toBe([]);
+ expect($example->toArray())
+ ->toBeEmpty();
});
diff --git a/tests/Unit/Objects/ExternalDocsTest.php b/tests/Unit/Objects/ExternalDocsTest.php
index 9c37c38..eb7eca2 100644
--- a/tests/Unit/Objects/ExternalDocsTest.php
+++ b/tests/Unit/Objects/ExternalDocsTest.php
@@ -9,12 +9,11 @@
it('emits url and optional description', function (): void {
expect(ExternalDocs::create('https://example.com/docs')->toArray())->toBe([
'url' => 'https://example.com/docs',
- ]);
-
- expect(
- ExternalDocs::create('https://example.com/docs')->description('More info')->toArray(),
- )->toBe([
- 'url' => 'https://example.com/docs',
- 'description' => 'More info',
- ]);
+ ])
+ ->and(ExternalDocs::create('https://example.com/docs')->description('More info')
+ ->toArray())
+ ->toBe([
+ 'url' => 'https://example.com/docs',
+ 'description' => 'More info',
+ ]);
});
diff --git a/tests/Unit/Objects/HeaderTest.php b/tests/Unit/Objects/HeaderTest.php
index 78f4a3d..4794770 100644
--- a/tests/Unit/Objects/HeaderTest.php
+++ b/tests/Unit/Objects/HeaderTest.php
@@ -9,7 +9,8 @@
covers(Header::class);
it('emits nothing by default', function (): void {
- expect(Header::create()->toArray())->toBe([]);
+ expect(Header::create()->toArray())
+ ->toBeEmpty();
});
it('emits a schema-based header', function (): void {
diff --git a/tests/Unit/Objects/LinkTest.php b/tests/Unit/Objects/LinkTest.php
index 294ade0..3c94e2f 100644
--- a/tests/Unit/Objects/LinkTest.php
+++ b/tests/Unit/Objects/LinkTest.php
@@ -8,7 +8,8 @@
covers(Link::class);
it('emits nothing when empty', function (): void {
- expect(Link::create()->toArray())->toBe([]);
+ expect(Link::create()->toArray())
+ ->toBeEmpty();
});
it('emits operationId-based link', function (): void {
@@ -65,13 +66,14 @@
$array = $link->toArray();
- expect($array)->toHaveKey('requestBody');
- expect($array['requestBody'])->toBe([
- 'key' => 'value',
- ]);
+ expect($array)->toHaveKey('requestBody')
+ ->and($array['requestBody'])
+ ->toBe([
+ 'key' => 'value',
+ ]);
$keys = array_keys($array);
- expect(array_search('requestBody', $keys, true))->toBeGreaterThan(array_search('parameters', $keys, true));
+ expect(keyIndex($keys, 'requestBody'))->toBeGreaterThan(keyIndex($keys, 'parameters'));
});
it('inserts requestBody before description when no parameters present', function (): void {
@@ -84,7 +86,7 @@
expect($array)->toHaveKey('requestBody');
$keys = array_keys($array);
- expect(array_search('requestBody', $keys, true))->toBeLessThan(array_search('description', $keys, true));
+ expect(keyIndex($keys, 'requestBody'))->toBeLessThan(keyIndex($keys, 'description'));
});
it('inserts requestBody before server when no parameters or description', function (): void {
@@ -99,7 +101,7 @@
expect($array)->toHaveKey('requestBody');
$keys = array_keys($array);
- expect(array_search('requestBody', $keys, true))->toBeLessThan(array_search('server', $keys, true));
+ expect(keyIndex($keys, 'requestBody'))->toBeLessThan(keyIndex($keys, 'server'));
});
it('appends requestBody at end when no parameters, description, or server', function (): void {
@@ -111,6 +113,7 @@
$array = $link->toArray();
- expect($array)->toHaveKey('requestBody');
- expect(array_key_last($array))->toBe('requestBody');
+ expect($array)->toHaveKey('requestBody')
+ ->and(array_key_last($array))
+ ->toBe('requestBody');
});
diff --git a/tests/Unit/Objects/MediaTypeTest.php b/tests/Unit/Objects/MediaTypeTest.php
index bae6d4b..c0698a0 100644
--- a/tests/Unit/Objects/MediaTypeTest.php
+++ b/tests/Unit/Objects/MediaTypeTest.php
@@ -11,14 +11,28 @@
covers(MediaType::class);
it('knows its own content type', function (): void {
- expect(MediaType::json()->getContentType())->toBe('application/json');
- expect(MediaType::xml()->getContentType())->toBe('application/xml');
- expect(MediaType::form()->getContentType())->toBe('application/x-www-form-urlencoded');
- expect(MediaType::multipart()->getContentType())->toBe('multipart/form-data');
- expect(MediaType::text()->getContentType())->toBe('text/plain');
- expect(MediaType::html()->getContentType())->toBe('text/html');
- expect(MediaType::octetStream()->getContentType())->toBe('application/octet-stream');
- expect(MediaType::of('application/pdf')->getContentType())->toBe('application/pdf');
+ expect(MediaType::json()->getContentType())->toBe('application/json')
+ ->and(MediaType::xml()
+ ->getContentType())
+ ->toBe('application/xml')
+ ->and(MediaType::form()
+ ->getContentType())
+ ->toBe('application/x-www-form-urlencoded')
+ ->and(MediaType::multipart()
+ ->getContentType())
+ ->toBe('multipart/form-data')
+ ->and(MediaType::text()
+ ->getContentType())
+ ->toBe('text/plain')
+ ->and(MediaType::html()
+ ->getContentType())
+ ->toBe('text/html')
+ ->and(MediaType::octetStream()
+ ->getContentType())
+ ->toBe('application/octet-stream')
+ ->and(MediaType::of('application/pdf')
+ ->getContentType())
+ ->toBe('application/pdf');
});
it('accepts a JsonSchema and strips $schema/title when serialized', function (): void {
@@ -91,7 +105,7 @@
]);
$keys = array_keys($mediaType->toArray());
- expect(array_search('example', $keys, true))->toBeLessThan(array_search('encoding', $keys, true));
+ expect(keyIndex($keys, 'example'))->toBeLessThan(keyIndex($keys, 'encoding'));
});
it('example appears at end when only schema present', function (): void {
diff --git a/tests/Unit/Objects/OAuthFlowsTest.php b/tests/Unit/Objects/OAuthFlowsTest.php
index 4e9ae86..346c7d4 100644
--- a/tests/Unit/Objects/OAuthFlowsTest.php
+++ b/tests/Unit/Objects/OAuthFlowsTest.php
@@ -8,7 +8,8 @@
covers(OAuthFlows::class, OAuthFlow::class);
it('emits nothing by default', function (): void {
- expect(OAuthFlows::create()->toArray())->toBe([]);
+ expect(OAuthFlows::create()->toArray())
+ ->toBeEmpty();
});
it('emits all four flows when configured', function (): void {
diff --git a/tests/Unit/Objects/OperationTest.php b/tests/Unit/Objects/OperationTest.php
index ba02f7a..eea1775 100644
--- a/tests/Unit/Objects/OperationTest.php
+++ b/tests/Unit/Objects/OperationTest.php
@@ -20,18 +20,33 @@
covers(Operation::class);
it('knows its HTTP method', function (): void {
- expect(Operation::get()->getMethod())->toBe(HttpMethod::Get);
- expect(Operation::post()->getMethod())->toBe(HttpMethod::Post);
- expect(Operation::put()->getMethod())->toBe(HttpMethod::Put);
- expect(Operation::patch()->getMethod())->toBe(HttpMethod::Patch);
- expect(Operation::delete()->getMethod())->toBe(HttpMethod::Delete);
- expect(Operation::options()->getMethod())->toBe(HttpMethod::Options);
- expect(Operation::head()->getMethod())->toBe(HttpMethod::Head);
- expect(Operation::trace()->getMethod())->toBe(HttpMethod::Trace);
+ expect(Operation::get()->getMethod())->toBe(HttpMethod::Get)
+ ->and(Operation::post()
+ ->getMethod())
+ ->toBe(HttpMethod::Post)
+ ->and(Operation::put()
+ ->getMethod())
+ ->toBe(HttpMethod::Put)
+ ->and(Operation::patch()
+ ->getMethod())
+ ->toBe(HttpMethod::Patch)
+ ->and(Operation::delete()
+ ->getMethod())
+ ->toBe(HttpMethod::Delete)
+ ->and(Operation::options()
+ ->getMethod())
+ ->toBe(HttpMethod::Options)
+ ->and(Operation::head()
+ ->getMethod())
+ ->toBe(HttpMethod::Head)
+ ->and(Operation::trace()
+ ->getMethod())
+ ->toBe(HttpMethod::Trace);
});
it('emits nothing by default', function (): void {
- expect(Operation::get()->toArray())->toBe([]);
+ expect(Operation::get()->toArray())
+ ->toBeEmpty();
});
it('emits tags/summary/description/operationId/deprecated', function (): void {
@@ -182,6 +197,6 @@
->callback('onError', Callback::ref('OnError'));
$arr = $operation->toArray();
- expect($arr['callbacks'])->toHaveKey('onData');
- expect($arr['callbacks'])->toHaveKey('onError');
+ expect($arr['callbacks'])->toHaveKey('onData')
+ ->toHaveKey('onError');
});
diff --git a/tests/Unit/Objects/PathItemTest.php b/tests/Unit/Objects/PathItemTest.php
index 1359a52..9eec251 100644
--- a/tests/Unit/Objects/PathItemTest.php
+++ b/tests/Unit/Objects/PathItemTest.php
@@ -89,15 +89,17 @@
);
$result = $pathItem->toArray();
- expect($result['servers'])->toBe([
+ $servers = expectArray($result['servers']);
+ expect($servers)->toBe([
[
'url' => 'https://api.example.com',
],
[
'url' => 'https://staging.example.com',
],
- ]);
- expect(array_is_list($result['servers']))->toBeTrue();
+ ])
+ ->and($servers)
+ ->toBeList();
});
it('parameters() preserves values as a list', function (): void {
@@ -108,6 +110,9 @@
);
$result = $pathItem->toArray();
- expect(array_is_list($result['parameters']))->toBeTrue();
- expect($result['parameters'])->toHaveCount(2);
+ $parameters = expectArray($result['parameters']);
+ expect($parameters)
+ ->toBeList()
+ ->and($parameters)
+ ->toHaveCount(2);
});
diff --git a/tests/Unit/Objects/ReferenceTest.php b/tests/Unit/Objects/ReferenceTest.php
index 2013d83..cd5fd79 100644
--- a/tests/Unit/Objects/ReferenceTest.php
+++ b/tests/Unit/Objects/ReferenceTest.php
@@ -3,14 +3,12 @@
declare(strict_types=1);
use Cortex\OpenApi\Objects\Reference;
-use Cortex\OpenApi\Contracts\Serializable;
covers(Reference::class);
it('builds a basic $ref array', function (): void {
$reference = Reference::to('#/components/schemas/User');
- expect($reference)->toBeInstanceOf(Serializable::class);
expect($reference->toArray())->toBe([
'$ref' => '#/components/schemas/User',
]);
@@ -45,41 +43,50 @@
it('provides typed shortcuts for every component bucket', function (): void {
expect(Reference::schema('User')->toArray())->toBe([
'$ref' => '#/components/schemas/User',
- ]);
-
- expect(Reference::response('NotFound')->toArray())->toBe([
- '$ref' => '#/components/responses/NotFound',
- ]);
-
- expect(Reference::parameter('PetId')->toArray())->toBe([
- '$ref' => '#/components/parameters/PetId',
- ]);
-
- expect(Reference::requestBody('CreateUser')->toArray())->toBe([
- '$ref' => '#/components/requestBodies/CreateUser',
- ]);
-
- expect(Reference::header('RateLimit')->toArray())->toBe([
- '$ref' => '#/components/headers/RateLimit',
- ]);
-
- expect(Reference::example('Sample')->toArray())->toBe([
- '$ref' => '#/components/examples/Sample',
- ]);
-
- expect(Reference::link('NextPage')->toArray())->toBe([
- '$ref' => '#/components/links/NextPage',
- ]);
-
- expect(Reference::callback('OnCreate')->toArray())->toBe([
- '$ref' => '#/components/callbacks/OnCreate',
- ]);
-
- expect(Reference::securityScheme('BearerAuth')->toArray())->toBe([
- '$ref' => '#/components/securitySchemes/BearerAuth',
- ]);
-
- expect(Reference::pathItem('UserById')->toArray())->toBe([
- '$ref' => '#/components/pathItems/UserById',
- ]);
+ ])
+ ->and(Reference::response('NotFound')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/responses/NotFound',
+ ])
+ ->and(Reference::parameter('PetId')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/parameters/PetId',
+ ])
+ ->and(Reference::requestBody('CreateUser')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/requestBodies/CreateUser',
+ ])
+ ->and(Reference::header('RateLimit')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/headers/RateLimit',
+ ])
+ ->and(Reference::example('Sample')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/examples/Sample',
+ ])
+ ->and(Reference::link('NextPage')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/links/NextPage',
+ ])
+ ->and(Reference::callback('OnCreate')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/callbacks/OnCreate',
+ ])
+ ->and(Reference::securityScheme('BearerAuth')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/securitySchemes/BearerAuth',
+ ])
+ ->and(Reference::pathItem('UserById')
+ ->toArray())
+ ->toBe([
+ '$ref' => '#/components/pathItems/UserById',
+ ]);
});
diff --git a/tests/Unit/Objects/RequestBodyTest.php b/tests/Unit/Objects/RequestBodyTest.php
index c1f6456..3474e1b 100644
--- a/tests/Unit/Objects/RequestBodyTest.php
+++ b/tests/Unit/Objects/RequestBodyTest.php
@@ -90,7 +90,8 @@
it('json() accepts a Reference', function (): void {
$requestBody = RequestBody::create()->json(Reference::schema('CreateUser'));
- expect($requestBody->toArray()['content']['application/json'])->toBe([
+ $content = expectArray($requestBody->toArray()['content']);
+ expect($content['application/json'])->toBe([
'schema' => [
'$ref' => '#/components/schemas/CreateUser',
],
diff --git a/tests/Unit/Objects/ResponseTest.php b/tests/Unit/Objects/ResponseTest.php
index cd716bc..11ff408 100644
--- a/tests/Unit/Objects/ResponseTest.php
+++ b/tests/Unit/Objects/ResponseTest.php
@@ -12,37 +12,42 @@
covers(Response::class);
it('named 200 response uses "OK" description by default', function (): void {
- expect(Response::ok()->getStatusCode())->toBe('200');
- expect(Response::ok()->toArray())->toBe([
- 'description' => 'OK',
- ]);
+ expect(Response::ok()->getStatusCode())->toBe('200')
+ ->and(Response::ok()
+ ->toArray())
+ ->toBe([
+ 'description' => 'OK',
+ ]);
});
it('named 404 response', function (): void {
$response = Response::notFound();
- expect($response->getStatusCode())->toBe('404');
- expect($response->toArray())->toBe([
- 'description' => 'Not Found',
- ]);
+ expect($response->getStatusCode())->toBe('404')
+ ->and($response->toArray())
+ ->toBe([
+ 'description' => 'Not Found',
+ ]);
});
it('arbitrary status via status()', function (): void {
$response = Response::status(418)->description("I'm a teapot");
- expect($response->getStatusCode())->toBe('418');
- expect($response->toArray())->toBe([
- 'description' => "I'm a teapot",
- ]);
+ expect($response->getStatusCode())->toBe('418')
+ ->and($response->toArray())
+ ->toBe([
+ 'description' => "I'm a teapot",
+ ]);
});
it('default response uses the default key', function (): void {
$response = Response::default()->description('Unexpected error');
- expect($response->getStatusCode())->toBe('default');
- expect($response->toArray())->toBe([
- 'description' => 'Unexpected error',
- ]);
+ expect($response->getStatusCode())->toBe('default')
+ ->and($response->toArray())
+ ->toBe([
+ 'description' => 'Unexpected error',
+ ]);
});
it('emits content, headers, and links', function (): void {
@@ -125,7 +130,8 @@
it('json() accepts a Reference', function (): void {
$response = Response::notFound()->json(Reference::schema('Error'));
- expect($response->toArray()['content']['application/json'])->toBe([
+ $content = expectArray($response->toArray()['content']);
+ expect($content['application/json'])->toBe([
'schema' => [
'$ref' => '#/components/schemas/Error',
],
@@ -133,6 +139,7 @@
});
it('json() with no schema emits an empty application/json key', function (): void {
- expect(Response::ok()->json()->toArray())->toHaveKey('content');
- expect(Response::ok()->json()->toArray()['content'])->toHaveKey('application/json');
+ expect(Response::ok()->json()->toArray())->toHaveKey('content')
+ ->and(Response::ok()->json()->toArray()['content'])
+ ->toHaveKey('application/json');
});
diff --git a/tests/Unit/Objects/SecurityRequirementTest.php b/tests/Unit/Objects/SecurityRequirementTest.php
index 06d72be..6051999 100644
--- a/tests/Unit/Objects/SecurityRequirementTest.php
+++ b/tests/Unit/Objects/SecurityRequirementTest.php
@@ -19,5 +19,6 @@
});
it('builds an empty requirement (public access)', function (): void {
- expect(SecurityRequirement::public()->toArray())->toBe([]);
+ expect(SecurityRequirement::public()->toArray())
+ ->toBeEmpty();
});
diff --git a/tests/Unit/Objects/XmlTest.php b/tests/Unit/Objects/XmlTest.php
index e38f697..7127b37 100644
--- a/tests/Unit/Objects/XmlTest.php
+++ b/tests/Unit/Objects/XmlTest.php
@@ -7,7 +7,8 @@
covers(Xml::class);
it('emits nothing by default', function (): void {
- expect(Xml::create()->toArray())->toBe([]);
+ expect(Xml::create()->toArray())
+ ->toBeEmpty();
});
it('emits every field', function (): void {
diff --git a/tests/Unit/OpenApiTest.php b/tests/Unit/OpenApiTest.php
index 87d2092..ccbe999 100644
--- a/tests/Unit/OpenApiTest.php
+++ b/tests/Unit/OpenApiTest.php
@@ -120,8 +120,10 @@
});
it('knows its OpenAPI version enum', function (): void {
- expect(OpenApi::create(OpenApiVersion::V3_1_0)->getVersion())->toBe(OpenApiVersion::V3_1_0);
- expect(OpenApi::create(OpenApiVersion::V3_1_1)->getVersion())->toBe(OpenApiVersion::V3_1_1);
+ expect(OpenApi::create(OpenApiVersion::V3_1_0)->getVersion())->toBe(OpenApiVersion::V3_1_0)
+ ->and(OpenApi::create(OpenApiVersion::V3_1_1)
+ ->getVersion())
+ ->toBe(OpenApiVersion::V3_1_1);
});
it('supports vendor extensions at the root', function (): void {
@@ -129,7 +131,8 @@
->info(Info::create('x', '1'))
->x('x-internal', true);
- expect($openApi->toArray()['x-internal'])->toBe(true);
+ expect($openApi->toArray()['x-internal'])
+ ->toBeTrue();
});
it('path() adds a PathItem or Reference by explicit pattern', function (): void {
@@ -140,12 +143,12 @@
))
->path('/legacy', Reference::pathItem('LegacyUsers'));
- $arr = $openApi->toArray();
- expect($arr['paths'])->toHaveKey('/users');
- expect($arr['paths'])->toHaveKey('/legacy');
- expect($arr['paths']['/legacy'])->toBe([
- '$ref' => '#/components/pathItems/LegacyUsers',
- ]);
+ $paths = expectArray($openApi->toArray()['paths']);
+ expect($paths)->toHaveKeys(['/users', '/legacy'])
+ ->and($paths['/legacy'])
+ ->toBe([
+ '$ref' => '#/components/pathItems/LegacyUsers',
+ ]);
});
it('adds webhooks one at a time with webhook()', function (): void {
diff --git a/tests/Unit/Validation/ComponentsTest.php b/tests/Unit/Validation/ComponentsTest.php
index 9ec5736..5123773 100644
--- a/tests/Unit/Validation/ComponentsTest.php
+++ b/tests/Unit/Validation/ComponentsTest.php
@@ -16,7 +16,8 @@
Components::create()->schema('Invalid Key!', Schema::object()),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/components/schemas',
'The string should match pattern: ^[a-zA-Z0-9._-]+$',
);
diff --git a/tests/Unit/Validation/DocumentTest.php b/tests/Unit/Validation/DocumentTest.php
index bd92979..426a005 100644
--- a/tests/Unit/Validation/DocumentTest.php
+++ b/tests/Unit/Validation/DocumentTest.php
@@ -24,7 +24,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('accepts a minimal valid 3.1.1 document', function (): void {
@@ -36,7 +36,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('accepts a document with components, tags, and schemas', function (): void {
@@ -52,13 +52,14 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a document missing info', function (): void {
$openApi = OpenApi::create();
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/',
'The required properties (info) are missing',
);
@@ -69,7 +70,7 @@
->info(Info::create('x', '1.0.0'))
->components(Components::create()->schema('User', Schema::object()));
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('accepts a webhooks-only document without paths or components', function (): void {
@@ -81,14 +82,14 @@
),
]);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a document with info but no paths, components, or webhooks', function (): void {
$openApi = OpenApi::create()
->info(Info::create('x', '1.0.0'));
- expect($openApi)->toFailOpenApiValidation([
+ assertOpenApiValidationErrors($openApi, [
'/' => [
'The required properties (paths) are missing',
'The required properties (components) are missing',
diff --git a/tests/Unit/Validation/ExampleTest.php b/tests/Unit/Validation/ExampleTest.php
index 98b4294..db623f3 100644
--- a/tests/Unit/Validation/ExampleTest.php
+++ b/tests/Unit/Validation/ExampleTest.php
@@ -21,7 +21,8 @@
->externalValue('https://example.com/examples/user.json')),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/components/examples/Bad',
'The data must not match schema',
);
diff --git a/tests/Unit/Validation/LicenseTest.php b/tests/Unit/Validation/LicenseTest.php
index 9ea419f..09c9025 100644
--- a/tests/Unit/Validation/LicenseTest.php
+++ b/tests/Unit/Validation/LicenseTest.php
@@ -20,7 +20,8 @@
)
->components(Components::create()->schema('Empty', Schema::object()));
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/info/license',
'The data must not match schema',
);
diff --git a/tests/Unit/Validation/ParameterTest.php b/tests/Unit/Validation/ParameterTest.php
index 3e02bb6..8372fec 100644
--- a/tests/Unit/Validation/ParameterTest.php
+++ b/tests/Unit/Validation/ParameterTest.php
@@ -28,7 +28,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a parameter with neither schema nor content', function (): void {
@@ -42,7 +42,7 @@
),
);
- expect($openApi)->toFailOpenApiValidation([
+ assertOpenApiValidationErrors($openApi, [
'/paths/~1ping/get/parameters/0' => [
'The required properties (schema) are missing',
'The required properties (content) are missing',
@@ -61,7 +61,8 @@
),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/paths/~1items~1%7Bid%7D/get/parameters/0/required',
'The data must match the const value',
);
diff --git a/tests/Unit/Validation/PathsTest.php b/tests/Unit/Validation/PathsTest.php
index 4e97f76..54f652d 100644
--- a/tests/Unit/Validation/PathsTest.php
+++ b/tests/Unit/Validation/PathsTest.php
@@ -17,7 +17,8 @@
Operation::get()->responses(Response::ok()),
));
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/paths',
'Unevaluated object properties not allowed: noslash',
);
diff --git a/tests/Unit/Validation/RequestBodyTest.php b/tests/Unit/Validation/RequestBodyTest.php
index 2f378ee..12caadd 100644
--- a/tests/Unit/Validation/RequestBodyTest.php
+++ b/tests/Unit/Validation/RequestBodyTest.php
@@ -24,7 +24,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a requestBody with no content', function (): void {
@@ -36,7 +36,8 @@
Components::create()->requestBody('Body', RequestBody::create()),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/components/requestBodies/Body',
'The data (array) must match the type: object',
);
diff --git a/tests/Unit/Validation/ResponseTest.php b/tests/Unit/Validation/ResponseTest.php
index f139f3b..9ce7992 100644
--- a/tests/Unit/Validation/ResponseTest.php
+++ b/tests/Unit/Validation/ResponseTest.php
@@ -23,7 +23,8 @@
),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/paths/~1ping/get/responses',
'Unevaluated object properties not allowed: 99',
);
@@ -42,7 +43,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a response object missing its description', function (): void {
@@ -55,7 +56,8 @@
),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/paths/~1ping/get/responses/503',
'The data (array) must match the type: object',
);
@@ -74,7 +76,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects a link with neither operationRef nor operationId', function (): void {
@@ -88,7 +90,8 @@
),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/paths/~1ping/get/responses/200/links/Empty',
'The data (array) must match the type: object',
);
diff --git a/tests/Unit/Validation/SecuritySchemeTest.php b/tests/Unit/Validation/SecuritySchemeTest.php
index 3a89298..a2aa499 100644
--- a/tests/Unit/Validation/SecuritySchemeTest.php
+++ b/tests/Unit/Validation/SecuritySchemeTest.php
@@ -36,7 +36,7 @@
),
);
- expect($openApi)->toPassOpenApiValidation();
+ assertOpenApiValidationPasses($openApi);
});
it('rejects an oauth2 security scheme without flows', function (): void {
@@ -47,7 +47,8 @@
->securityScheme('oauth2', SecurityScheme::oauth2()),
);
- expect($openApi)->toFailOpenApiValidationAt(
+ assertOpenApiValidationFailsAt(
+ $openApi,
'/components/securitySchemes/oauth2',
'The required properties (flows) are missing',
);
diff --git a/tests/Unit/Validation/ValidationExceptionTest.php b/tests/Unit/Validation/ValidationExceptionTest.php
index 2c1beed..fbb9d27 100644
--- a/tests/Unit/Validation/ValidationExceptionTest.php
+++ b/tests/Unit/Validation/ValidationExceptionTest.php
@@ -3,6 +3,7 @@
declare(strict_types=1);
use Cortex\OpenApi\OpenApi;
+use PHPUnit\Framework\Assert;
use Cortex\OpenApi\Exceptions\ValidationException;
covers(OpenApi::class);
@@ -12,7 +13,7 @@
try {
$openApi->validate();
- $this->fail('Expected ValidationException');
+ Assert::fail('Expected ValidationException');
} catch (ValidationException $validationException) {
expect($validationException->getMessage())->toContain('OpenAPI document failed meta-schema validation:');
}
@@ -39,18 +40,18 @@
try {
$openApi->validate();
- expect(true)->toBeFalse('Expected ValidationException');
+ Assert::fail('Expected ValidationException');
} catch (ValidationException $validationException) {
$errors = $validationException->errors();
- expect($errors)->toBeArray();
- expect($errors)->not->toBeEmpty();
- expect($errors)->toHaveKey('/');
- expect($errors['/'])->toBeArray();
- expect($errors['/'][0])->toBe('The required properties (info) are missing');
+ expect($errors)->not->toBeEmpty()
+ ->toHaveKey('/');
+ $rootErrors = expectArray($errors['/']);
+ expect($rootErrors[0])->toBe('The required properties (info) are missing');
}
});
it('ValidationException constructed without errors returns empty array from errors()', function (): void {
$e = new ValidationException('Something went wrong');
- expect($e->errors())->toBe([]);
+ expect($e->errors())
+ ->toBeEmpty();
});
diff --git a/tests/phpstan/pest-expectations.stub b/tests/phpstan/pest-expectations.stub
deleted file mode 100644
index cf8d9aa..0000000
--- a/tests/phpstan/pest-expectations.stub
+++ /dev/null
@@ -1,18 +0,0 @@
- toFailOpenApiValidation(array> $expectedErrors)
- * @method self toFailOpenApiValidationAt(string $pointer, string $message)
- * @method self toPassOpenApiValidation()
- */
-class Expectation
-{
-}