From fcbfb5f7840226d198d43962ba9849a136799cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Wed, 28 Jan 2026 17:35:36 +0100 Subject: [PATCH 1/7] Remove sidux/collection + bump guzzle --- composer.json | 8 ++--- src/Definition/Api.php | 4 +-- src/Definition/Body.php | 11 ++----- src/Definition/Collection/Comparable.php | 19 ++++++++++++ .../Collection/OperationExamples.php | 2 +- src/Definition/Collection/Operations.php | 4 ++- src/Definition/Collection/Parameters.php | 2 +- src/Definition/Collection/Responses.php | 1 + src/Definition/Example/OperationExample.php | 7 +++-- src/Definition/Operation.php | 30 ++++++++++--------- src/Definition/Parameter.php | 8 ++--- src/Definition/Response.php | 29 ++++-------------- src/Definition/Scope.php | 4 +-- src/Definition/Security.php | 2 +- src/Definition/Server.php | 2 +- src/Definition/Tag.php | 2 +- src/Definition/Token.php | 16 +++++----- src/Preparator/Error403Preparator.php | 2 +- src/Preparator/Error404Preparator.php | 21 +++++++------ src/Preparator/Error405Preparator.php | 4 +-- src/Preparator/Error406Preparator.php | 2 +- src/Preparator/SecurityErrorPreparator.php | 10 +++++-- 22 files changed, 96 insertions(+), 94 deletions(-) create mode 100644 src/Definition/Collection/Comparable.php diff --git a/composer.json b/composer.json index cd14edf8..3b9f4261 100644 --- a/composer.json +++ b/composer.json @@ -52,12 +52,12 @@ "fakerphp/faker": "^1.9", "firebase/php-jwt": "^6.0.0", "guzzlehttp/promises": "^1.4.0", - "illuminate/collections": "^8.0", + "illuminate/collections": "^12.0", + "league/openapi-psr7-validator": "^0.18", "monolog/monolog": "^1.25.1 || ^2.8.0 || ^3.0.0", "myclabs/deep-copy": "^1.11", "nesbot/carbon": "^2.48", "nyholm/psr7": "1.*", - "league/openapi-psr7-validator": "^0.18", "openclassrooms/openapi-psr7-validator": "dev-master", "opis/json-schema": "^2.3", "php-http/httplug": "^2.2", @@ -100,10 +100,6 @@ "veewee/composer-run-parallel": "^1.1" }, "repositories": [ - { - "type": "vcs", - "url": "https://github.com/sidux/collections" - }, { "type": "vcs", "url": "https://github.com/OpenClassrooms/openapi-psr7-validator" diff --git a/src/Definition/Api.php b/src/Definition/Api.php index 7266d71b..208e8a1f 100644 --- a/src/Definition/Api.php +++ b/src/Definition/Api.php @@ -106,7 +106,7 @@ public function getScopes(): Collection { /** @var Collection */ return $this->getSecurities() - ->select('scopes') + ->pluck('scopes') ->flatten() ->unique() ; @@ -119,7 +119,7 @@ public function getSecurities(): Collection { /** @var Collection */ return $this->getOperations() - ->select('securities.*') + ->pluck('securities.*') ->flatten() ; } diff --git a/src/Definition/Body.php b/src/Definition/Body.php index abc5ae91..137e7fce 100644 --- a/src/Definition/Body.php +++ b/src/Definition/Body.php @@ -13,9 +13,9 @@ final class Body { private Operation $parent; - private readonly Schema $schema; + public readonly Schema $schema; - private bool $required = false; + public bool $required = false; /** * @param Schema|array $schema @@ -24,7 +24,7 @@ final class Body */ public function __construct( $schema, - private readonly string $mediaType = 'application/json' + public readonly string $mediaType = 'application/json' ) { $this->schema = $schema instanceof Schema ? $schema : new Schema($schema); } @@ -51,11 +51,6 @@ public function setRequired(bool $required = true): self return $this; } - public function getMediaType(): string - { - return $this->mediaType; - } - public function getParent(): Operation { return $this->parent; diff --git a/src/Definition/Collection/Comparable.php b/src/Definition/Collection/Comparable.php new file mode 100644 index 00000000..b0fe8974 --- /dev/null +++ b/src/Definition/Collection/Comparable.php @@ -0,0 +1,19 @@ + $items + * + * @return static + */ + public function compare(iterable $items): self + { + return $this->diff($items) + ->merge(collect($items)->diff($this)) + ; + } +} diff --git a/src/Definition/Collection/OperationExamples.php b/src/Definition/Collection/OperationExamples.php index 67ae9253..58f6cc9c 100644 --- a/src/Definition/Collection/OperationExamples.php +++ b/src/Definition/Collection/OperationExamples.php @@ -17,7 +17,7 @@ final class OperationExamples extends Collection /** * @var OperationExample[] */ - protected array $examples; + public array $examples; /** * @param OperationExample[] $examples diff --git a/src/Definition/Collection/Operations.php b/src/Definition/Collection/Operations.php index f99fd5f8..866969df 100644 --- a/src/Definition/Collection/Operations.php +++ b/src/Definition/Collection/Operations.php @@ -14,6 +14,8 @@ */ final class Operations extends Collection { + use Comparable; + /** * @return array> */ @@ -23,7 +25,7 @@ public function toPropIndexedArray(): array foreach ($this as $operation) { $operations[$operation->getMethod()][] = $operation; $operations[$operation->getId()][] = $operation; - foreach ($operation->getTags()->select('name') as $tag) { + foreach ($operation->getTags()->pluck('name') as $tag) { $operations[(string) $tag][] = $operation; } } diff --git a/src/Definition/Collection/Parameters.php b/src/Definition/Collection/Parameters.php index c95ad677..19bb78bd 100644 --- a/src/Definition/Collection/Parameters.php +++ b/src/Definition/Collection/Parameters.php @@ -19,7 +19,7 @@ final class Parameters extends Collection /** * @var Parameter[] */ - protected $items; + public $items; /** * @return array diff --git a/src/Definition/Collection/Responses.php b/src/Definition/Collection/Responses.php index c3978003..87836494 100644 --- a/src/Definition/Collection/Responses.php +++ b/src/Definition/Collection/Responses.php @@ -14,4 +14,5 @@ */ final class Responses extends Collection { + use Comparable; } diff --git a/src/Definition/Example/OperationExample.php b/src/Definition/Example/OperationExample.php index 37302346..40bd8a0b 100644 --- a/src/Definition/Example/OperationExample.php +++ b/src/Definition/Example/OperationExample.php @@ -51,7 +51,7 @@ final class OperationExample private DeepCopy $deepCopy; public function __construct( - private string $name, + public string $name, Operation $parent = null, ?int $statusCode = null, ) { @@ -380,7 +380,7 @@ public function setAuthenticationHeaders(Tokens $tokens, bool $ignoreScope = fal foreach ($operation->getSecurities() as $security) { $scopes = $security->getScopes() ->where('name', '!=', 'current_user') - ->select('name') + ->pluck('name') ->toArray() ; @@ -392,7 +392,8 @@ public function setAuthenticationHeaders(Tokens $tokens, bool $ignoreScope = fal $token = $tokens->filter( static fn (Token $token) => $token->getFilters()?->includes($operation) ?? false ) - ->first() ?? $tokens->where('scopes', 'includes', $scopes) + ->first() ?? $tokens->filter( + fn (Token $t) => count(array_diff($scopes, $t->getScopes())) === 0) ->first() ; } diff --git a/src/Definition/Operation.php b/src/Definition/Operation.php index 94a503c2..21ff5b6f 100644 --- a/src/Definition/Operation.php +++ b/src/Definition/Operation.php @@ -21,7 +21,7 @@ final class Operation implements Filterable private string $description = ''; - private Parameters $headers; + public Parameters $headers; private Api $parent; @@ -31,27 +31,27 @@ final class Operation implements Filterable private Parameters $queryParameters; - private Bodies $bodies; + public Bodies $bodies; - private Responses $responses; + public readonly Responses $responses; - private Securities $securities; + public readonly Securities $securities; private string $summary = ''; - private Tags $tags; + public Tags $tags; - private OperationExamples $examples; + public OperationExamples $examples; /** * @var array */ - private array $extensions; + public array $extensions; public function __construct( - private readonly string $id, - private readonly string $path, - private string $method + public readonly string $id, + public readonly string $path, + public string $method ) { $this->pathParameters = new Parameters(); $this->queryParameters = new Parameters(); @@ -197,10 +197,11 @@ public function getResponses(): Responses public function setResponses(Responses $responses): self { + $this->responses->forget($this->responses->keys()); + foreach ($responses as $response) { - $response->setParent($this); + $this->responses->add($response); } - $this->responses = $responses; return $this; } @@ -220,7 +221,6 @@ public function getResponse(int $status): ?Response public function addResponse(Response $response): self { - $response->setParent($this); $this->responses->add($response); return $this; @@ -382,10 +382,12 @@ public function getSecurities(): Securities public function setSecurities(Securities $securities): self { + $this->securities->forget($this->securities->keys()); + foreach ($securities as $security) { $security->setParent($this); + $this->securities->add($security); } - $this->securities = $securities; return $this; } diff --git a/src/Definition/Parameter.php b/src/Definition/Parameter.php index 0ba5e99b..b19ddb57 100644 --- a/src/Definition/Parameter.php +++ b/src/Definition/Parameter.php @@ -18,16 +18,16 @@ final class Parameter private Operation $parent; - private string $in; + public string $in; - private ?Schema $schema; + public ?Schema $schema; /** * @param Schema|array|null $schema */ public function __construct( - private readonly string $name, - private bool $required = true, + public readonly string $name, + public bool $required = true, $schema = null ) { if (\is_array($schema)) { diff --git a/src/Definition/Response.php b/src/Definition/Response.php index d70bcf79..6747aead 100644 --- a/src/Definition/Response.php +++ b/src/Definition/Response.php @@ -9,18 +9,16 @@ final class Response { - private Operation $parent; + public ?string $mediaType = null; - private ?string $mediaType = null; + public Parameters $headers; - private Parameters $headers; + public ?Schema $body = null; - private ?Schema $body = null; - - private string $description = ''; + public string $description = ''; public function __construct( - private int $statusCode + public readonly int $statusCode ) { $this->headers = new Parameters(); } @@ -47,13 +45,6 @@ public function getStatusCode(): int return $this->statusCode; } - public function setStatusCode(int $statusCode): self - { - $this->statusCode = $statusCode; - - return $this; - } - public function getHeaders(): Parameters { return $this->headers; @@ -100,14 +91,4 @@ public function setDescription(string $description): self return $this; } - - public function getParent(): Operation - { - return $this->parent; - } - - public function setParent(Operation $parent): void - { - $this->parent = $parent; - } } diff --git a/src/Definition/Scope.php b/src/Definition/Scope.php index 6541c74f..cd122c16 100644 --- a/src/Definition/Scope.php +++ b/src/Definition/Scope.php @@ -7,8 +7,8 @@ final class Scope { public function __construct( - private readonly string $name, - private readonly string $description = '' + public readonly string $name, + public readonly string $description = '' ) { } diff --git a/src/Definition/Security.php b/src/Definition/Security.php index f7be70ad..83e62037 100644 --- a/src/Definition/Security.php +++ b/src/Definition/Security.php @@ -26,7 +26,7 @@ abstract class Security protected string $name; - protected Scopes $scopes; + public readonly Scopes $scopes; public function __construct(string $name, ?Scopes $scopes = null) { diff --git a/src/Definition/Server.php b/src/Definition/Server.php index 984f27de..c2a276a8 100644 --- a/src/Definition/Server.php +++ b/src/Definition/Server.php @@ -7,7 +7,7 @@ final class Server { public function __construct( - private readonly string $url + public readonly string $url ) { } diff --git a/src/Definition/Tag.php b/src/Definition/Tag.php index 056ee58b..69116115 100644 --- a/src/Definition/Tag.php +++ b/src/Definition/Tag.php @@ -7,7 +7,7 @@ final class Tag { public function __construct( - private readonly string $name + public readonly string $name ) { } diff --git a/src/Definition/Token.php b/src/Definition/Token.php index 91cc5979..7210b663 100644 --- a/src/Definition/Token.php +++ b/src/Definition/Token.php @@ -8,20 +8,20 @@ final class Token { - private readonly string $type; + public readonly string $type; - private readonly int $expiresIn; + public readonly int $expiresIn; /** * @param string[] $scopes */ public function __construct( - private readonly string $name, - private readonly string $authType, - private readonly string $accessToken, - private readonly array $scopes = [], - private readonly ?string $refreshToken = null, - private readonly ?Filters $filters = null, + public readonly string $name, + public readonly string $authType, + public readonly string $accessToken, + public readonly array $scopes = [], + public readonly ?string $refreshToken = null, + public readonly ?Filters $filters = null, ?string $type = null, ?int $expiresIn = null ) { diff --git a/src/Preparator/Error403Preparator.php b/src/Preparator/Error403Preparator.php index 51581e94..51e5e550 100644 --- a/src/Preparator/Error403Preparator.php +++ b/src/Preparator/Error403Preparator.php @@ -32,7 +32,7 @@ protected function getTestTokens(Security $security): Tokens fn (Token $x) => !\in_array($x->getName(), $this->config->excludedTokens, true) && $security ->getScopes() - ->select('name') + ->pluck('name') ->intersect($x->getScopes()) ->count() === 0 ) diff --git a/src/Preparator/Error404Preparator.php b/src/Preparator/Error404Preparator.php index 08302be9..31a5cb6c 100644 --- a/src/Preparator/Error404Preparator.php +++ b/src/Preparator/Error404Preparator.php @@ -7,7 +7,8 @@ use APITester\Definition\Collection\Operations; use APITester\Definition\Example\OperationExample; use APITester\Definition\Example\ResponseExample; -use APITester\Definition\Response as DefinitionResponse; +use APITester\Definition\Operation; +use APITester\Definition\Response; use APITester\Test\TestCase; final class Error404Preparator extends TestCasesPreparator @@ -19,14 +20,14 @@ protected function prepare(Operations $operations): iterable { /** @var iterable */ return $operations - ->select('responses.*') + ->map( + fn (Operation $operation) => $operation->responses + ->where('statusCode', 404) + ->values() + ->map(fn (Response $response) => $this->prepareTestCase($operation, $response)) + ) ->flatten() - ->where('statusCode', 404) - ->values() - ->map(function ($response) { - /** @var DefinitionResponse $response */ - return $this->prepareTestCase($response); - }) + ->flatten() ; } @@ -34,10 +35,8 @@ protected function prepare(Operations $operations): iterable /** * @return array */ - private function prepareTestCase(DefinitionResponse $response): array + private function prepareTestCase(Operation $operation, Response $response): array { - $operation = $response->getParent(); - $testcases = []; if ($operation->getRequestBodies()->count() === 0) { diff --git a/src/Preparator/Error405Preparator.php b/src/Preparator/Error405Preparator.php index 6195da07..be63e3cd 100644 --- a/src/Preparator/Error405Preparator.php +++ b/src/Preparator/Error405Preparator.php @@ -24,8 +24,8 @@ protected function prepare(Operations $operations): iterable { /** @var iterable */ return $operations->groupBy('path', true) - ->map(fn (Collection $pathOperations) => $pathOperations - ->select('method') + ->map(fn (Operations $pathOperations) => $pathOperations + ->pluck('method') ->intersect($this->config->methods) ->compare($this->config->methods) ->crossJoin($pathOperations->take(1)) diff --git a/src/Preparator/Error406Preparator.php b/src/Preparator/Error406Preparator.php index 93141eb7..9e894a01 100644 --- a/src/Preparator/Error406Preparator.php +++ b/src/Preparator/Error406Preparator.php @@ -24,7 +24,7 @@ protected function prepare(Operations $operations): iterable /** @var iterable */ return $operations->map( fn (Operation $operation) => $operation->getResponses() - ->select('mediaType') + ->pluck('mediaType') ->intersect($this->config->mediaTypes) ->compare($this->config->mediaTypes) ->shuffle() diff --git a/src/Preparator/SecurityErrorPreparator.php b/src/Preparator/SecurityErrorPreparator.php index ff056b5a..73b6b0ac 100644 --- a/src/Preparator/SecurityErrorPreparator.php +++ b/src/Preparator/SecurityErrorPreparator.php @@ -8,6 +8,8 @@ use APITester\Definition\Collection\Tokens; use APITester\Definition\Example\OperationExample; use APITester\Definition\Example\ResponseExample; +use APITester\Definition\Operation; +use APITester\Definition\Response; use APITester\Definition\Security; use APITester\Test\TestCase; use Illuminate\Support\Collection; @@ -21,8 +23,12 @@ protected function prepare(Operations $operations): iterable { /** @var iterable */ return $operations - ->where('responses.*.statusCode', 'contains', (int) $this->getStatusCode()) - ->select('securities.*') + ->filter( + fn (Operation $o) => $o->getResponses()->filter( + fn (Response $r) => $r->getStatusCode() === (int) $this->getStatusCode() + ) + ) + ->pluck('securities.*') ->flatten() ->map(function ($security) { /** @var Security $security */ From 12982328fab9228d1f7f5f3da00ec3e640dad6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Wed, 28 Jan 2026 17:41:17 +0100 Subject: [PATCH 2/7] Remove deleted deps --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 3b9f4261..7cd3876f 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,6 @@ "pyrech/composer-changelogs": "^1.8", "rector/rector": "^0.15.23", "roave/security-advisories": "dev-latest", - "dereuromark/composer-versions-check": "^0.1", "spaze/phpstan-disallowed-calls": "^2.1", "symfony/var-dumper": "^5.0 || ^6.0", "symplify/easy-coding-standard": "^11.3.0", From a202a0c9b20ce45db651667793bfe7354fb1f08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Thu, 29 Jan 2026 11:42:39 +0100 Subject: [PATCH 3/7] Various little fixes --- composer.json | 3 --- src/Config/Suite.php | 2 +- .../Loader/OpenApiDefinitionLoader.php | 7 +++---- src/Definition/Operation.php | 16 ---------------- src/Definition/Security.php | 14 -------------- src/Preparator/Error404Preparator.php | 2 -- src/Preparator/SecurityErrorPreparator.php | 16 ++++++---------- src/Preparator/TestCasesPreparator.php | 4 ++++ src/Test/Suite.php | 6 +----- 9 files changed, 15 insertions(+), 55 deletions(-) diff --git a/composer.json b/composer.json index 7cd3876f..7d8695b9 100644 --- a/composer.json +++ b/composer.json @@ -51,16 +51,13 @@ "cebe/php-openapi": "^1.5", "fakerphp/faker": "^1.9", "firebase/php-jwt": "^6.0.0", - "guzzlehttp/promises": "^1.4.0", "illuminate/collections": "^12.0", "league/openapi-psr7-validator": "^0.18", - "monolog/monolog": "^1.25.1 || ^2.8.0 || ^3.0.0", "myclabs/deep-copy": "^1.11", "nesbot/carbon": "^2.48", "nyholm/psr7": "1.*", "openclassrooms/openapi-psr7-validator": "dev-master", "opis/json-schema": "^2.3", - "php-http/httplug": "^2.2", "phpdocumentor/reflection-docblock": "^5.3", "phpstan/phpdoc-parser": "^1.2", "phpunit/phpunit": "^9.5", diff --git a/src/Config/Suite.php b/src/Config/Suite.php index 4f7451b2..80306e8c 100644 --- a/src/Config/Suite.php +++ b/src/Config/Suite.php @@ -42,7 +42,7 @@ final class Suite private ?string $baseUrl = null; public function __construct( - private readonly string $name, + public readonly string $name, private readonly Definition $definition ) { $this->filters = new Filters(); diff --git a/src/Definition/Loader/OpenApiDefinitionLoader.php b/src/Definition/Loader/OpenApiDefinitionLoader.php index 8aff352f..12dd9ca3 100644 --- a/src/Definition/Loader/OpenApiDefinitionLoader.php +++ b/src/Definition/Loader/OpenApiDefinitionLoader.php @@ -43,6 +43,7 @@ use cebe\openapi\spec\RequestBody; use cebe\openapi\spec\Schema; use cebe\openapi\spec\SecurityRequirement; +use cebe\openapi\spec\SecurityRequirements; use cebe\openapi\spec\SecurityScheme; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -117,7 +118,7 @@ private function getOperations(array $paths, array $securitySchemes, array $filt /** @var RequestBody $requestBody */ $requestBody = $operation->requestBody; $responses = $operation->responses; - $requirements = $this->getSecurityRequirementsScopes($operation->security ?? []); + $requirements = $this->getSecurityRequirementsScopes($operation->security ?? new SecurityRequirements([])); $operations->add( Operation::create( @@ -174,11 +175,9 @@ private function getTags(array $tags): Tags } /** - * @param SecurityRequirement[] $securityRequirements - * * @return array */ - private function getSecurityRequirementsScopes(array $securityRequirements): array + private function getSecurityRequirementsScopes(SecurityRequirements $securityRequirements): array { $requirements = []; foreach ($securityRequirements as $requirement) { diff --git a/src/Definition/Operation.php b/src/Definition/Operation.php index 21ff5b6f..be42c985 100644 --- a/src/Definition/Operation.php +++ b/src/Definition/Operation.php @@ -27,8 +27,6 @@ final class Operation implements Filterable private Parameters $pathParameters; - private string $preparator; - private Parameters $queryParameters; public Bodies $bodies; @@ -228,7 +226,6 @@ public function addResponse(Response $response): self public function addSecurity(Security $security): self { - $security->setParent($this); $this->securities->add($security); return $this; @@ -363,18 +360,6 @@ public function setParent(Api $parent): void $this->parent = $parent; } - public function getPreparator(): string - { - return $this->preparator; - } - - public function setPreparator(string $string): self - { - $this->preparator = $string; - - return $this; - } - public function getSecurities(): Securities { return $this->securities; @@ -385,7 +370,6 @@ public function setSecurities(Securities $securities): self $this->securities->forget($this->securities->keys()); foreach ($securities as $security) { - $security->setParent($this); $this->securities->add($security); } diff --git a/src/Definition/Security.php b/src/Definition/Security.php index 83e62037..69f7e151 100644 --- a/src/Definition/Security.php +++ b/src/Definition/Security.php @@ -20,8 +20,6 @@ abstract class Security public const SCHEME_BEARER_AUTH = 'bearer'; - protected Operation $parent; - protected string $description = ''; protected string $name; @@ -34,18 +32,6 @@ public function __construct(string $name, ?Scopes $scopes = null) $this->scopes = $scopes ?? new Scopes(); } - final public function getParent(): Operation - { - return $this->parent; - } - - final public function setParent(Operation $parent): self - { - $this->parent = $parent; - - return $this; - } - final public function getDescription(): string { return $this->description; diff --git a/src/Preparator/Error404Preparator.php b/src/Preparator/Error404Preparator.php index 31a5cb6c..bcdd18dc 100644 --- a/src/Preparator/Error404Preparator.php +++ b/src/Preparator/Error404Preparator.php @@ -27,8 +27,6 @@ protected function prepare(Operations $operations): iterable ->map(fn (Response $response) => $this->prepareTestCase($operation, $response)) ) ->flatten() - - ->flatten() ; } diff --git a/src/Preparator/SecurityErrorPreparator.php b/src/Preparator/SecurityErrorPreparator.php index 73b6b0ac..1838fa72 100644 --- a/src/Preparator/SecurityErrorPreparator.php +++ b/src/Preparator/SecurityErrorPreparator.php @@ -28,14 +28,11 @@ protected function prepare(Operations $operations): iterable fn (Response $r) => $r->getStatusCode() === (int) $this->getStatusCode() ) ) - ->pluck('securities.*') - ->flatten() - ->map(function ($security) { - /** @var Security $security */ - return $this->prepareTestCases($security); - }) - ->flatten() - ; + ->map(fn (Operation $operation) => $operation->getSecurities() + ->map(fn (Security $security) => $this->prepareTestCases($operation, $security)) + ->flatten() + ) + ->flatten(); } abstract protected function getStatusCode(): string; @@ -47,9 +44,8 @@ abstract protected function getTestCaseName(): string; /** * @return Collection */ - private function prepareTestCases(Security $security): iterable + private function prepareTestCases(Operation $operation, Security $security): iterable { - $operation = $security->getParent(); $tokens = $this->getTestTokens($security); /** @var Collection $testCases */ $testCases = collect(); diff --git a/src/Preparator/TestCasesPreparator.php b/src/Preparator/TestCasesPreparator.php index 51399d3d..80fafe0c 100644 --- a/src/Preparator/TestCasesPreparator.php +++ b/src/Preparator/TestCasesPreparator.php @@ -30,6 +30,8 @@ abstract class TestCasesPreparator protected LoggerInterface $logger; + public readonly string $name; + /** * @var array */ @@ -41,6 +43,8 @@ public function __construct() $this->config = $this->newConfigInstance(static::getConfigFQCN()); $this->logger = new NullLogger(); $this->schemaValidationBaseline = []; + + $this->name = static::getName(); } /** diff --git a/src/Test/Suite.php b/src/Test/Suite.php index 54198980..122c901c 100644 --- a/src/Test/Suite.php +++ b/src/Test/Suite.php @@ -149,11 +149,7 @@ private function prepareTestCases(): void foreach ($this->preparators as $preparator) { $preparator->setLogger($this->logger); $preparator->setSchemaValidationBaseline($this->filters->getSchemaValidationBaseline()); - $operations = $this->api->getOperations() - ->map( - static fn (Operation $op) => $op->setPreparator($preparator::getName()) - ) - ; + $operations = $this->api->getOperations(); try { $operations = $this->filterOperation($operations); $tests = $preparator->doPrepare($operations); From c462aa36354c41bfe8a408997724272f196b3e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Thu, 29 Jan 2026 12:17:08 +0100 Subject: [PATCH 4/7] Fixing phpstan --- composer.json | 32 +- config/phpstan-baseline.neon | 471 +++++++++++++++++- config/phpstan.neon | 4 - src/Config/Loader/PlanConfigLoader.php | 2 +- src/Definition/Api.php | 2 - src/Definition/Body.php | 4 +- src/Definition/Collection/Comparable.php | 1 + src/Definition/Collection/Operations.php | 1 - src/Definition/Collection/Responses.php | 1 - src/Definition/Example/OperationExample.php | 5 +- .../Loader/OpenApiDefinitionLoader.php | 5 +- src/Definition/Operation.php | 20 +- src/Definition/Parameter.php | 4 +- src/Definition/Security.php | 4 +- .../OAuth2ClientCredentialsSecurity.php | 1 - src/Preparator/Error400Preparator.php | 1 - src/Preparator/Error404Preparator.php | 3 +- src/Preparator/Error405Preparator.php | 2 - src/Preparator/Error406Preparator.php | 5 +- src/Preparator/ExamplesPreparator.php | 7 +- src/Preparator/PaginationErrorPreparator.php | 1 - src/Preparator/RandomPreparator.php | 5 +- src/Preparator/SecurityErrorPreparator.php | 15 +- src/Preparator/TestCasesPreparator.php | 4 +- 24 files changed, 502 insertions(+), 98 deletions(-) diff --git a/composer.json b/composer.json index 7d8695b9..d00b1742 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "openclassrooms/openapi-psr7-validator": "dev-master", "opis/json-schema": "^2.3", "phpdocumentor/reflection-docblock": "^5.3", - "phpstan/phpdoc-parser": "^1.2", + "phpstan/phpdoc-parser": "^1.2 || ^2.0", "phpunit/phpunit": "^9.5", "psr/http-client": "^1.0", "psr/http-message": "1.*", @@ -76,24 +76,21 @@ }, "require-dev": { "ergebnis/composer-normalize": "^2.25", - "ergebnis/phpstan-rules": "^1.0", - "korbeil/phpstan-generic-rules": "^1.0", - "nunomaduro/phpinsights": "^2.1", + "ergebnis/phpstan-rules": "^2.0", + "korbeil/phpstan-generic-rules": "^2.0", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.6", - "phpstan/phpstan-beberlei-assert": "^1.0", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpstan/phpstan-symfony": "^1.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-beberlei-assert": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-symfony": "^2.0", "pyrech/composer-changelogs": "^1.8", - "rector/rector": "^0.15.23", + "rector/rector": "^2.3", "roave/security-advisories": "dev-latest", - "spaze/phpstan-disallowed-calls": "^2.1", + "spaze/phpstan-disallowed-calls": "^4.7", "symfony/var-dumper": "^5.0 || ^6.0", - "symplify/easy-coding-standard": "^11.3.0", - "thecodingmachine/phpstan-strict-rules": "^1.0", - "veewee/composer-run-parallel": "^1.1" + "symplify/easy-coding-standard": "^11.3" }, "repositories": [ { @@ -108,11 +105,6 @@ "@check-static", "@test" ], - "parallel-check": [ - "@parallel fix-cs", - "@parallel check-static", - "@parallel test" - ], "check-cs": [ "vendor/bin/ecs check --ansi -c config/ecs.php" ], diff --git a/config/phpstan-baseline.neon b/config/phpstan-baseline.neon index bca07137..d5b49580 100644 --- a/config/phpstan-baseline.neon +++ b/config/phpstan-baseline.neon @@ -1,86 +1,517 @@ parameters: ignoreErrors: - - message: "#^PHPDoc tag @var with type Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\), APITester\\\\Definition\\\\Security\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Config\Suite::getPreparators() should return array> but returns array.' + identifier: return.type + count: 1 + path: ../src/Config/Suite.php + + - + rawMessage: 'Method APITester\Definition\Api::getScopes() should return Illuminate\Support\Collection<(int|string), string> but returns Illuminate\Support\Collection.' + identifier: return.type count: 1 path: ../src/Definition/Api.php - - message: "#^PHPDoc tag @var with type Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\), string\\> is not subtype of type Illuminate\\\\Support\\\\Collection\\\\.$#" + rawMessage: 'Method APITester\Definition\Api::getSecurities() should return Illuminate\Support\Collection<(int|string), APITester\Definition\Security> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Definition/Api.php - - message: "#^Cannot cast APITester\\\\Definition\\\\Tag to string\\.$#" + rawMessage: 'Call to method __construct() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Definition/Body.php + + - + rawMessage: 'Call to method generate() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Definition/Body.php + + - + rawMessage: Instantiation of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker. + identifier: new.internalClass + count: 1 + path: ../src/Definition/Body.php + + - + rawMessage: Cannot cast APITester\Definition\Tag to string. + identifier: cast.string count: 1 path: ../src/Definition/Collection/Operations.php - - message: "#^PHPDoc tag @var with type APITester\\\\Definition\\\\Example\\\\OperationExample is not subtype of type \\$this\\(APITester\\\\Definition\\\\Example\\\\OperationExample\\)\\.$#" - count: 2 - path: ../src/Definition/Example/OperationExample.php + rawMessage: 'PHPDoc tag @return contains generic type static(APITester\Definition\Collection\Operations) but class APITester\Definition\Collection\Operations is not generic.' + identifier: generics.notGeneric + count: 1 + path: ../src/Definition/Collection/Operations.php + + - + rawMessage: 'Parameter #1 $items of method Illuminate\Support\Collection<(int|string),APITester\Definition\Operation>::diff() expects Illuminate\Contracts\Support\Arrayable<(int|string), APITester\Definition\Operation>|iterable<(int|string), APITester\Definition\Operation>, iterable<(int|string), APITester\Definition\Collection\TValue> given.' + identifier: argument.type + count: 1 + path: ../src/Definition/Collection/Operations.php + + - + rawMessage: 'Parameter $items of method APITester\Definition\Collection\Operations::compare() has invalid type APITester\Definition\Collection\TValue.' + identifier: class.notFound + count: 1 + path: ../src/Definition/Collection/Operations.php + + - + rawMessage: 'Call to method __construct() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Definition/Collection/Parameters.php + + - + rawMessage: 'Call to method generate() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Definition/Collection/Parameters.php + + - + rawMessage: Instantiation of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker. + identifier: new.internalClass + count: 1 + path: ../src/Definition/Collection/Parameters.php + + - + rawMessage: 'PHPDoc tag @return contains generic type static(APITester\Definition\Collection\Responses) but class APITester\Definition\Collection\Responses is not generic.' + identifier: generics.notGeneric + count: 1 + path: ../src/Definition/Collection/Responses.php + + - + rawMessage: 'Parameter #1 $items of method Illuminate\Support\Collection<(int|string),APITester\Definition\Response>::diff() expects Illuminate\Contracts\Support\Arrayable<(int|string), APITester\Definition\Response>|iterable<(int|string), APITester\Definition\Response>, iterable<(int|string), APITester\Definition\Collection\TValue> given.' + identifier: argument.type + count: 1 + path: ../src/Definition/Collection/Responses.php + + - + rawMessage: 'Parameter $items of method APITester\Definition\Collection\Responses::compare() has invalid type APITester\Definition\Collection\TValue.' + identifier: class.notFound + count: 1 + path: ../src/Definition/Collection/Responses.php + + - + rawMessage: 'Argument of an invalid type cebe\openapi\spec\SecurityRequirements supplied for foreach, only iterables are supported.' + identifier: foreach.nonIterable + count: 1 + path: ../src/Definition/Loader/OpenApiDefinitionLoader.php + + - + rawMessage: 'Method APITester\Definition\Loader\OpenApiDefinitionLoader::extractDeepExamples() is invoked with named argument for parameter $path.' + identifier: ergebnis.noNamedArgument + count: 3 + path: ../src/Definition/Loader/OpenApiDefinitionLoader.php + + - + rawMessage: 'Method APITester\Definition\Loader\OpenApiDefinitionLoader::getExample() has parameter $examples that is passed by reference.' + identifier: ergebnis.noParameterPassedByReference + count: 1 + path: ../src/Definition/Loader/OpenApiDefinitionLoader.php + + - + rawMessage: 'Parameter #1 $securityRequirements of method APITester\Definition\Loader\OpenApiDefinitionLoader::getSecurityRequirementsScopes() expects cebe\openapi\spec\SecurityRequirements, array|cebe\openapi\spec\SecurityRequirements given.' + identifier: argument.type + count: 1 + path: ../src/Definition/Loader/OpenApiDefinitionLoader.php + + - + rawMessage: Cannot cast APITester\Definition\Example\OperationExample|null to string. + identifier: cast.string + count: 1 + path: ../src/Definition/Operation.php - - message: "#^Cannot cast APITester\\\\Definition\\\\Example\\\\OperationExample\\|null to string\\.$#" + rawMessage: 'Parameter #2 $replace of function str_replace expects array|string, list given.' + identifier: argument.type count: 1 path: ../src/Definition/Operation.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: Property APITester\Definition\Operation::$method on left side of ?? is not nullable nor uninitialized. + identifier: nullCoalesce.initializedProperty + count: 1 + path: ../src/Definition/Operation.php + + - + rawMessage: Readonly property APITester\Definition\Security::$scopes is assigned outside of its declaring class. + identifier: property.readOnlyAssignOutOfClass + count: 1 + path: ../src/Definition/Security/OAuth2/OAuth2AuthorizationCodeSecurity.php + + - + rawMessage: 'Method APITester\Preparator\Error400Preparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/Error400Preparator.php - - message: "#^Parameter \\#1 \\$items of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),APITester\\\\Definition\\\\Scope\\>\\:\\:intersect\\(\\) expects Illuminate\\\\Contracts\\\\Support\\\\Arrayable\\<\\(int\\|string\\), APITester\\\\Definition\\\\Scope\\>\\|iterable\\<\\(int\\|string\\), APITester\\\\Definition\\\\Scope\\>, array\\ given\\.$#" + rawMessage: 'Parameter #1 $items of method Illuminate\Support\Collection<(int|string),APITester\Definition\Scope>::intersect() expects Illuminate\Contracts\Support\Arrayable<(int|string), APITester\Definition\Scope>|iterable<(int|string), APITester\Definition\Scope>, array given.' + identifier: argument.type count: 1 path: ../src/Preparator/Error403Preparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\Error404Preparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/Error404Preparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\Error405Preparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type + count: 1 + path: ../src/Preparator/Error405Preparator.php + + - + rawMessage: 'Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),APITester\Definition\Operation>::map() expects callable(APITester\Definition\Operation, int|string): APITester\Definition\Collection\Operations, Closure(APITester\Definition\Collection\Operations): APITester\Definition\Collection\Operations given.' + identifier: argument.type + count: 1 + path: ../src/Preparator/Error405Preparator.php + + - + rawMessage: 'Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),APITester\Definition\Operation>::map() expects callable(APITester\Definition\Operation, int|string): APITester\Test\TestCase, Closure(array): APITester\Test\TestCase given.' + identifier: argument.type + count: 1 + path: ../src/Preparator/Error405Preparator.php + + - + rawMessage: 'Parameter #1 $items of method APITester\Definition\Collection\Operations::compare() expects iterable<(int|string), APITester\Definition\Collection\TValue>, array given.' + identifier: argument.type + count: 1 + path: ../src/Preparator/Error405Preparator.php + + - + rawMessage: 'Parameter #1 $items of method Illuminate\Support\Collection<(int|string),APITester\Definition\Operation>::intersect() expects Illuminate\Contracts\Support\Arrayable<(int|string), APITester\Definition\Operation>|iterable<(int|string), APITester\Definition\Operation>, array given.' + identifier: argument.type count: 1 path: ../src/Preparator/Error405Preparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\Error406Preparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/Error406Preparator.php - - message: "#^Parameter \\#1 \\$items of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),APITester\\\\Definition\\\\Response\\>\\:\\:compare\\(\\) expects iterable\\<\\(int\\|string\\), APITester\\\\Definition\\\\Response\\>, array\\ given\\.$#" + rawMessage: 'Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),APITester\Definition\Response>::map() expects callable(APITester\Definition\Response, int|string): APITester\Test\TestCase, Closure(string): APITester\Test\TestCase given.' + identifier: argument.type count: 1 path: ../src/Preparator/Error406Preparator.php - - message: "#^Parameter \\#1 \\$items of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),APITester\\\\Definition\\\\Response\\>\\:\\:intersect\\(\\) expects Illuminate\\\\Contracts\\\\Support\\\\Arrayable\\<\\(int\\|string\\), APITester\\\\Definition\\\\Response\\>\\|iterable\\<\\(int\\|string\\), APITester\\\\Definition\\\\Response\\>, array\\ given\\.$#" + rawMessage: 'Parameter #1 $items of method APITester\Definition\Collection\Responses::compare() expects iterable<(int|string), APITester\Definition\Collection\TValue>, array given.' + identifier: argument.type count: 1 path: ../src/Preparator/Error406Preparator.php - - message: "#^Method APITester\\\\Preparator\\\\ExamplesPreparator\\:\\:prepareTestCases\\(\\) should return iterable\\ but returns APITester\\\\Definition\\\\Collection\\\\OperationExamples\\.$#" + rawMessage: 'Parameter #1 $items of method Illuminate\Support\Collection<(int|string),APITester\Definition\Response>::intersect() expects Illuminate\Contracts\Support\Arrayable<(int|string), APITester\Definition\Response>|iterable<(int|string), APITester\Definition\Response>, array given.' + identifier: argument.type count: 1 - path: ../src/Preparator/ExamplesPreparator.php + path: ../src/Preparator/Error406Preparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\ExamplesPreparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/ExamplesPreparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\PaginationErrorPreparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/PaginationErrorPreparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\RandomPreparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/RandomPreparator.php - - message: "#^PHPDoc tag @var with type iterable\\<\\(int\\|string\\), APITester\\\\Test\\\\TestCase\\> is not subtype of type APITester\\\\Definition\\\\Collection\\\\Operations\\.$#" + rawMessage: 'Method APITester\Preparator\SecurityErrorPreparator::prepare() should return iterable<(int|string), APITester\Test\TestCase> but returns APITester\Definition\Collection\Operations.' + identifier: return.type count: 1 path: ../src/Preparator/SecurityErrorPreparator.php + + - + rawMessage: 'PHPDoc tag @var with type Illuminate\Support\Collection<(int|string), APITester\Test\TestCase> is not subtype of type Illuminate\Support\Collection<*NEVER*, *NEVER*>.' + identifier: varTag.type + count: 1 + path: ../src/Preparator/SecurityErrorPreparator.php + + - + rawMessage: 'Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),APITester\Definition\Operation>::filter() expects (callable(APITester\Definition\Operation, int|string): bool)|null, Closure(APITester\Definition\Operation): APITester\Definition\Collection\Responses given.' + identifier: argument.type + count: 1 + path: ../src/Preparator/SecurityErrorPreparator.php + + - + rawMessage: 'Call to method __construct() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Preparator/TestCasesPreparator.php + + - + rawMessage: 'Call to method generate() of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker from outside its root namespace Vural.' + identifier: method.internalClass + count: 1 + path: ../src/Preparator/TestCasesPreparator.php + + - + rawMessage: Instantiation of internal class Vural\OpenAPIFaker\SchemaFaker\SchemaFaker. + identifier: new.internalClass + count: 1 + path: ../src/Preparator/TestCasesPreparator.php + + - + rawMessage: 'Call to method then() of internal class Symfony\Component\HttpClient\Response\HttplugPromise from outside its root namespace Symfony.' + identifier: method.internalClass + count: 1 + path: ../src/Requester/HttpAsyncRequester.php + + - + rawMessage: 'Call to method __construct() of internal class PHPUnit\TextUI\TestRunner from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method errorCount() of internal class PHPUnit\Framework\TestResult from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method errors() of internal class PHPUnit\Framework\TestResult from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method failedTest() of internal class PHPUnit\Framework\TestFailure from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method failureCount() of internal class PHPUnit\Framework\TestResult from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method failures() of internal class PHPUnit\Framework\TestResult from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method fromParameters() of internal class PHPUnit\TextUI\CliArguments\Builder from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method load() of internal class PHPUnit\TextUI\XmlConfiguration\Loader from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method mapToLegacyArray() of internal class PHPUnit\TextUI\CliArguments\Mapper from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method run() of internal class PHPUnit\TextUI\TestRunner from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Instantiation of internal class PHPUnit\TextUI\CliArguments\Builder. + identifier: new.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Instantiation of internal class PHPUnit\TextUI\CliArguments\Mapper. + identifier: new.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Instantiation of internal class PHPUnit\TextUI\TestRunner. + identifier: new.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Instantiation of internal class PHPUnit\TextUI\XmlConfiguration\Loader. + identifier: new.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Method APITester\Definition\Loader\DefinitionLoader::load() is invoked with named argument for parameter $filters.' + identifier: ergebnis.noNamedArgument + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Property $results references internal class PHPUnit\Framework\TestResult in its type. + identifier: property.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: Property $runner references internal class PHPUnit\TextUI\TestRunner in its type. + identifier: property.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Return type of method APITester\Test\Plan::getResults() has typehint with internal class PHPUnit\Framework\TestResult.' + identifier: return.internalClass + count: 1 + path: ../src/Test/Plan.php + + - + rawMessage: 'Call to method __construct() of internal class PHPUnit\Framework\TestSuite from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: 'Call to method addTest() of internal class PHPUnit\Framework\TestSuite from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: 'Call to method run() of internal class PHPUnit\Framework\TestSuite from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: Class APITester\Test\Suite extends internal class PHPUnit\Framework\TestSuite. + identifier: class.extendsInternalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: 'PHPDoc tag @var with type Illuminate\Support\Collection is not subtype of type Illuminate\Support\Collection<*NEVER*, *NEVER*>.' + identifier: varTag.type + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: 'Parameter $result of method APITester\Test\Suite::run() has typehint with internal class PHPUnit\Framework\TestResult.' + identifier: parameter.internalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: 'Return type of method APITester\Test\Suite::run() has typehint with internal class PHPUnit\Framework\TestResult.' + identifier: return.internalClass + count: 1 + path: ../src/Test/Suite.php + + - + rawMessage: Catching internal class PHPUnit\Framework\ExpectationFailedException. + identifier: catch.internalClass + count: 1 + path: ../src/Test/TestCase.php + + - + rawMessage: 'Call to method getTestName() of internal class PHPUnit\Framework\TestFailure from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Util/TestCase/Printer/DefaultPrinter.php + + - + rawMessage: 'Call to method write() of internal class PHPUnit\Util\Printer from outside its root namespace PHPUnit.' + identifier: method.internalClass + count: 1 + path: ../src/Util/TestCase/Printer/DefaultPrinter.php + + - + rawMessage: Class APITester\Util\TestCase\Printer\DefaultPrinter extends internal class PHPUnit\TextUI\DefaultResultPrinter. + identifier: class.extendsInternalClass + count: 1 + path: ../src/Util/TestCase/Printer/DefaultPrinter.php + + - + rawMessage: 'Parameter $defect of method APITester\Util\TestCase\Printer\DefaultPrinter::printDefectHeader() has typehint with internal class PHPUnit\Framework\TestFailure.' + identifier: parameter.internalClass + count: 1 + path: ../src/Util/TestCase/Printer/DefaultPrinter.php + + - + rawMessage: 'Parameter $defect of method APITester\Util\TestCase\Printer\DefaultPrinter::printDefectTrace() has typehint with internal class PHPUnit\Framework\TestFailure.' + identifier: parameter.internalClass + count: 1 + path: ../src/Util/TestCase/Printer/DefaultPrinter.php + + - + rawMessage: Class APITester\Util\TestCase\Printer\TestDoxPrinter extends internal class PHPUnit\Util\TestDox\CliTestDoxPrinter. + identifier: class.extendsInternalClass + count: 1 + path: ../src/Util/TestCase/Printer/TestDoxPrinter.php + + - + rawMessage: Constructor of APITester\Config\Filters is invoked with named argument for parameter $include. + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Preparator/ExamplesPreparatorTest.php + + - + rawMessage: Constructor of APITester\Config\Filters is invoked with named argument for parameter $schemaValidationBaseline. + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Preparator/ExamplesPreparatorTest.php + + - + rawMessage: Constructor of APITester\Definition\Token is invoked with named argument for parameter $filters. + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Preparator/ExamplesPreparatorTest.php + + - + rawMessage: Constructor of APITester\Test\TestCase is invoked with named argument for parameter $schemaValidation. + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Preparator/ExamplesPreparatorTest.php + + - + rawMessage: 'Method APITester\Definition\Security\HttpSecurity::create() is invoked with named argument for parameter $scopes.' + identifier: ergebnis.noNamedArgument + count: 2 + path: ../tests/Preparator/ExamplesPreparatorTest.php + + - + rawMessage: 'Method APITester\Definition\Example\OperationExample::create() is invoked with named argument for parameter $name.' + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Test/TestCaseTest.php + + - + rawMessage: 'Method APITester\Definition\Example\OperationExample::create() is invoked with named argument for parameter $operation.' + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Test/TestCaseTest.php + + - + rawMessage: 'Method APITester\Definition\Example\OperationExample::create() is invoked with named argument for parameter $statusCode.' + identifier: ergebnis.noNamedArgument + count: 1 + path: ../tests/Test/TestCaseTest.php diff --git a/config/phpstan.neon b/config/phpstan.neon index c62836d8..2a255b69 100644 --- a/config/phpstan.neon +++ b/config/phpstan.neon @@ -24,14 +24,10 @@ parameters: - '/Class ".+" is not allowed to extend ".+"./' - '/Variable property access on .+./' - '/Method .+ is not final, but since the containing class is abstract, it should be./' - - '/Unable to resolve the template type TKey in call to function collect/' - - '/Unable to resolve the template type TValue in call to function collect/' - '/Class APITester\\Preparator\\Config\\PreparatorConfig is neither abstract nor final./' - '/Instantiated class \\ApiTestCase not found./' - '/Instantiated class \\TestCaseKernelProvider not found./' - '/Construct empty\(\) is not allowed. Use more strict comparison./' - - '/Language construct empty\(\) should not be used./' - - '/In method "APITester\\Requester\\SymfonyKernelRequester::request", caught "Throwable" must be rethrown.+/' - '/.+ APITester\\Test\\TestCase\|null is not subtype of type PHPUnit\\Framework\\Test\|null/' - {paths: [ ../tests ], message: '/Method .+ throws checked exception .+ but it''s missing from the PHPDoc @throws tag./'} - {paths: [ ../src/Test/TestCase.php, ../src/Test/Plan.php ], message: '/Calling eval\(\) is forbidden, eval is evil, please write more code and do not use eval\(\)/'} diff --git a/src/Config/Loader/PlanConfigLoader.php b/src/Config/Loader/PlanConfigLoader.php index 0a510d60..a18b321e 100644 --- a/src/Config/Loader/PlanConfigLoader.php +++ b/src/Config/Loader/PlanConfigLoader.php @@ -41,7 +41,7 @@ private static function process(string $content): string throw new ConfigurationException("Environment variable '{$var}' is not defined."); } $patterns[] = "/%env\\({$var}\\)%/i"; - $replacements[] = $env; + $replacements[] = (string) $env; } } diff --git a/src/Definition/Api.php b/src/Definition/Api.php index 208e8a1f..db4a554c 100644 --- a/src/Definition/Api.php +++ b/src/Definition/Api.php @@ -104,7 +104,6 @@ public function setTags(Tags $tags): self */ public function getScopes(): Collection { - /** @var Collection */ return $this->getSecurities() ->pluck('scopes') ->flatten() @@ -117,7 +116,6 @@ public function getScopes(): Collection */ public function getSecurities(): Collection { - /** @var Collection */ return $this->getOperations() ->pluck('securities.*') ->flatten() diff --git a/src/Definition/Body.php b/src/Definition/Body.php index 137e7fce..1f874c3a 100644 --- a/src/Definition/Body.php +++ b/src/Definition/Body.php @@ -11,12 +11,12 @@ final class Body { - private Operation $parent; - public readonly Schema $schema; public bool $required = false; + private Operation $parent; + /** * @param Schema|array $schema * diff --git a/src/Definition/Collection/Comparable.php b/src/Definition/Collection/Comparable.php index b0fe8974..427108b3 100644 --- a/src/Definition/Collection/Comparable.php +++ b/src/Definition/Collection/Comparable.php @@ -1,4 +1,5 @@ */ final class Operations extends Collection diff --git a/src/Definition/Collection/Responses.php b/src/Definition/Collection/Responses.php index 87836494..e78182fb 100644 --- a/src/Definition/Collection/Responses.php +++ b/src/Definition/Collection/Responses.php @@ -9,7 +9,6 @@ /** * @method Response[] getIterator() - * @method Responses map(callable $c) * @extends Collection */ final class Responses extends Collection diff --git a/src/Definition/Example/OperationExample.php b/src/Definition/Example/OperationExample.php index 40bd8a0b..4aa8ae64 100644 --- a/src/Definition/Example/OperationExample.php +++ b/src/Definition/Example/OperationExample.php @@ -75,7 +75,6 @@ public function setPathParameter(string $name, string $value): self public function withParameter(string $name, string $value, string $in): self { - /** @var self $clone */ $clone = $this->deepCopy->copy($this); $clone->setParameter($name, $value, $in); @@ -160,7 +159,6 @@ public static function create(string $name, ?Operation $operation = null, ?int $ public function withBody(BodyExample $body): self { - /** @var self $clone */ $clone = $this->deepCopy->copy($this); $clone->setBody($body); @@ -393,7 +391,8 @@ public function setAuthenticationHeaders(Tokens $tokens, bool $ignoreScope = fal static fn (Token $token) => $token->getFilters()?->includes($operation) ?? false ) ->first() ?? $tokens->filter( - fn (Token $t) => count(array_diff($scopes, $t->getScopes())) === 0) + static fn (Token $t) => count(array_diff($scopes, $t->getScopes())) === 0 + ) ->first() ; } diff --git a/src/Definition/Loader/OpenApiDefinitionLoader.php b/src/Definition/Loader/OpenApiDefinitionLoader.php index 12dd9ca3..277b9ef6 100644 --- a/src/Definition/Loader/OpenApiDefinitionLoader.php +++ b/src/Definition/Loader/OpenApiDefinitionLoader.php @@ -42,7 +42,6 @@ use cebe\openapi\spec\PathItem; use cebe\openapi\spec\RequestBody; use cebe\openapi\spec\Schema; -use cebe\openapi\spec\SecurityRequirement; use cebe\openapi\spec\SecurityRequirements; use cebe\openapi\spec\SecurityScheme; use Psr\Log\LoggerInterface; @@ -118,7 +117,9 @@ private function getOperations(array $paths, array $securitySchemes, array $filt /** @var RequestBody $requestBody */ $requestBody = $operation->requestBody; $responses = $operation->responses; - $requirements = $this->getSecurityRequirementsScopes($operation->security ?? new SecurityRequirements([])); + $requirements = $this->getSecurityRequirementsScopes( + $operation->security ?? new SecurityRequirements([]) + ); $operations->add( Operation::create( diff --git a/src/Definition/Operation.php b/src/Definition/Operation.php index be42c985..e45c1458 100644 --- a/src/Definition/Operation.php +++ b/src/Definition/Operation.php @@ -19,24 +19,14 @@ final class Operation implements Filterable { use FilterableTrait; - private string $description = ''; - public Parameters $headers; - private Api $parent; - - private Parameters $pathParameters; - - private Parameters $queryParameters; - public Bodies $bodies; public readonly Responses $responses; public readonly Securities $securities; - private string $summary = ''; - public Tags $tags; public OperationExamples $examples; @@ -46,6 +36,16 @@ final class Operation implements Filterable */ public array $extensions; + private string $description = ''; + + private Api $parent; + + private Parameters $pathParameters; + + private Parameters $queryParameters; + + private string $summary = ''; + public function __construct( public readonly string $id, public readonly string $path, diff --git a/src/Definition/Parameter.php b/src/Definition/Parameter.php index b19ddb57..d0dfd32a 100644 --- a/src/Definition/Parameter.php +++ b/src/Definition/Parameter.php @@ -16,12 +16,12 @@ final class Parameter public const TYPES = [self::TYPE_QUERY, self::TYPE_PATH, self::TYPE_HEADER]; - private Operation $parent; - public string $in; public ?Schema $schema; + private Operation $parent; + /** * @param Schema|array|null $schema */ diff --git a/src/Definition/Security.php b/src/Definition/Security.php index 69f7e151..0065a46a 100644 --- a/src/Definition/Security.php +++ b/src/Definition/Security.php @@ -20,12 +20,12 @@ abstract class Security public const SCHEME_BEARER_AUTH = 'bearer'; + public readonly Scopes $scopes; + protected string $description = ''; protected string $name; - public readonly Scopes $scopes; - public function __construct(string $name, ?Scopes $scopes = null) { $this->name = mb_strtolower($name); diff --git a/src/Definition/Security/OAuth2/OAuth2ClientCredentialsSecurity.php b/src/Definition/Security/OAuth2/OAuth2ClientCredentialsSecurity.php index 0bb4b550..0be016a0 100644 --- a/src/Definition/Security/OAuth2/OAuth2ClientCredentialsSecurity.php +++ b/src/Definition/Security/OAuth2/OAuth2ClientCredentialsSecurity.php @@ -14,7 +14,6 @@ public function __construct( Scopes $scopes ) { parent::__construct($name, $scopes); - $this->scopes = $scopes; } public static function create(string $name, string $tokenUrl, Scopes $scopes): self diff --git a/src/Preparator/Error400Preparator.php b/src/Preparator/Error400Preparator.php index 03b54d92..135f1a7d 100644 --- a/src/Preparator/Error400Preparator.php +++ b/src/Preparator/Error400Preparator.php @@ -21,7 +21,6 @@ abstract class Error400Preparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations ->map(fn (Operation $operation) => $this->prepareTestCases($operation)) ->flatten() diff --git a/src/Preparator/Error404Preparator.php b/src/Preparator/Error404Preparator.php index bcdd18dc..bb16265d 100644 --- a/src/Preparator/Error404Preparator.php +++ b/src/Preparator/Error404Preparator.php @@ -18,13 +18,12 @@ final class Error404Preparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations ->map( fn (Operation $operation) => $operation->responses ->where('statusCode', 404) ->values() - ->map(fn (Response $response) => $this->prepareTestCase($operation, $response)) + ->map(fn (Response $response) => $this->prepareTestCase($operation, $response)) ) ->flatten() ; diff --git a/src/Preparator/Error405Preparator.php b/src/Preparator/Error405Preparator.php index be63e3cd..5341491d 100644 --- a/src/Preparator/Error405Preparator.php +++ b/src/Preparator/Error405Preparator.php @@ -10,7 +10,6 @@ use APITester\Definition\Operation; use APITester\Preparator\Config\Error405PreparatorConfig; use APITester\Test\TestCase; -use Illuminate\Support\Collection; /** * @property Error405PreparatorConfig $config @@ -22,7 +21,6 @@ final class Error405Preparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations->groupBy('path', true) ->map(fn (Operations $pathOperations) => $pathOperations ->pluck('method') diff --git a/src/Preparator/Error406Preparator.php b/src/Preparator/Error406Preparator.php index 9e894a01..72af217c 100644 --- a/src/Preparator/Error406Preparator.php +++ b/src/Preparator/Error406Preparator.php @@ -21,7 +21,6 @@ final class Error406Preparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations->map( fn (Operation $operation) => $operation->getResponses() ->pluck('mediaType') @@ -30,9 +29,9 @@ protected function prepare(Operations $operations): iterable ->shuffle() ->take($this->config->casesCount) ->sort() - ->map(fn ($type) => $this->prepareTestCase( + ->map(fn (string $type) => $this->prepareTestCase( $operation, - (string) $type + $type )) )->flatten(); } diff --git a/src/Preparator/ExamplesPreparator.php b/src/Preparator/ExamplesPreparator.php index 1cc5bbc7..581cf5a0 100644 --- a/src/Preparator/ExamplesPreparator.php +++ b/src/Preparator/ExamplesPreparator.php @@ -11,7 +11,6 @@ use APITester\Definition\Operation; use APITester\Preparator\Config\ExamplesPreparatorConfig; use APITester\Preparator\Exception\PreparatorLoadingException; -use APITester\Test\TestCase; use Symfony\Component\Serializer\Exception\ExceptionInterface; /** @@ -26,7 +25,6 @@ protected function prepare(Operations $operations): iterable { $operations = $this->handleExtension($operations); - /** @var iterable */ return $operations ->map(fn (Operation $operation) => $this->prepareTestCases($operation)) ->flatten() @@ -52,10 +50,7 @@ private function handleExtension(Operations $operations): Operations return $operations; } - /** - * @return iterable - */ - private function prepareTestCases(Operation $operation): iterable + private function prepareTestCases(Operation $operation): OperationExamples { $examples = $operation->getExamples(); if ($this->config->autoCreateWhenMissing && $examples->count() === 0) { diff --git a/src/Preparator/PaginationErrorPreparator.php b/src/Preparator/PaginationErrorPreparator.php index d5ccf1a2..71b16cf7 100644 --- a/src/Preparator/PaginationErrorPreparator.php +++ b/src/Preparator/PaginationErrorPreparator.php @@ -23,7 +23,6 @@ abstract class PaginationErrorPreparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations ->map(fn (Operation $operation) => $this->prepareTestCases($operation)) ->flatten() diff --git a/src/Preparator/RandomPreparator.php b/src/Preparator/RandomPreparator.php index aad1cf5b..93ed06ae 100644 --- a/src/Preparator/RandomPreparator.php +++ b/src/Preparator/RandomPreparator.php @@ -19,7 +19,6 @@ final class RandomPreparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations ->map(fn (Operation $operation) => $this->prepareTestCases($operation)) ->flatten() @@ -27,9 +26,9 @@ protected function prepare(Operations $operations): iterable } /** - * @return iterable + * @return TestCase[] */ - private function prepareTestCases(Operation $operation): iterable + private function prepareTestCases(Operation $operation): array { $testCases = []; foreach (range(1, $this->config->casesCount) as $ignored) { diff --git a/src/Preparator/SecurityErrorPreparator.php b/src/Preparator/SecurityErrorPreparator.php index 1838fa72..448347f9 100644 --- a/src/Preparator/SecurityErrorPreparator.php +++ b/src/Preparator/SecurityErrorPreparator.php @@ -21,16 +21,17 @@ abstract class SecurityErrorPreparator extends TestCasesPreparator */ protected function prepare(Operations $operations): iterable { - /** @var iterable */ return $operations ->filter( - fn (Operation $o) => $o->getResponses()->filter( - fn (Response $r) => $r->getStatusCode() === (int) $this->getStatusCode() - ) + fn (Operation $o) => $o->getResponses() + ->filter( + fn (Response $r) => $r->getStatusCode() === (int) $this->getStatusCode() + ) ) - ->map(fn (Operation $operation) => $operation->getSecurities() - ->map(fn (Security $security) => $this->prepareTestCases($operation, $security)) - ->flatten() + ->map( + fn (Operation $operation) => $operation->getSecurities() + ->map(fn (Security $security) => $this->prepareTestCases($operation, $security)) + ->flatten() ) ->flatten(); } diff --git a/src/Preparator/TestCasesPreparator.php b/src/Preparator/TestCasesPreparator.php index 80fafe0c..4cb68e6b 100644 --- a/src/Preparator/TestCasesPreparator.php +++ b/src/Preparator/TestCasesPreparator.php @@ -24,14 +24,14 @@ abstract class TestCasesPreparator { + public readonly string $name; + protected Tokens $tokens; protected PreparatorConfig $config; protected LoggerInterface $logger; - public readonly string $name; - /** * @var array */ From a2e639c3577fe7ec39744981a928a6eb639a8cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Thu, 29 Jan 2026 12:29:14 +0100 Subject: [PATCH 5/7] Move vendor works --- composer.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index d00b1742..9342fbd7 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "cebe/php-openapi": "^1.5", "fakerphp/faker": "^1.9", "firebase/php-jwt": "^6.0.0", - "illuminate/collections": "^12.0", + "illuminate/collections": "^11.0 || ^12.0", "league/openapi-psr7-validator": "^0.18", "myclabs/deep-copy": "^1.11", "nesbot/carbon": "^2.48", @@ -63,16 +63,16 @@ "phpunit/phpunit": "^9.5", "psr/http-client": "^1.0", "psr/http-message": "1.*", - "symfony/console": "^5.0 || ^6.0", - "symfony/dotenv": "^5.0 || ^6.0", - "symfony/finder": "^5.0 || ^6.0", - "symfony/http-client": "^5.0 || ^6.0", - "symfony/http-kernel": "^5.0 || ^6.0", - "symfony/property-access": "^5.0 || ^6.0 || ^6.0", - "symfony/property-info": "^5.0 || ^6.0", - "symfony/psr-http-message-bridge": "^1.2 || ^2.1.2", - "symfony/serializer": "^5.0 || ^6.0", - "symfony/yaml": "^5.0 || ^6.0" + "symfony/console": "^5.0 || ^6.0 || ^7.0", + "symfony/dotenv": "^5.0 || ^6.0 || ^7.0", + "symfony/finder": "^5.0 || ^6.0 || ^7.0", + "symfony/http-client": "^5.0 || ^6.0 || ^7.0", + "symfony/http-kernel": "^5.0 || ^6.0 || ^7.0", + "symfony/property-access": "^5.0 || ^6.0 || ^7.0", + "symfony/property-info": "^5.0 || ^6.0 || ^7.0", + "symfony/psr-http-message-bridge": "^2.1|| ^6.0 || ^7.0", + "symfony/serializer": "^5.0 || ^6.0 || ^7.0", + "symfony/yaml": "^5.0 || ^6.0 || ^7.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.25", @@ -89,7 +89,7 @@ "rector/rector": "^2.3", "roave/security-advisories": "dev-latest", "spaze/phpstan-disallowed-calls": "^4.7", - "symfony/var-dumper": "^5.0 || ^6.0", + "symfony/var-dumper": "^5.0 || ^6.0 || ^7.0", "symplify/easy-coding-standard": "^11.3" }, "repositories": [ From c950490cf189a5cca73d01d1f00f5f5c383ca628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Thu, 29 Jan 2026 12:41:48 +0100 Subject: [PATCH 6/7] Add sf 7 --- config/phpstan-baseline.neon | 48 +++++++++++++++++++ src/Util/Normalizer/PsrRequestNormalizer.php | 32 ++++++++----- src/Util/Normalizer/PsrResponseNormalizer.php | 25 ++++++---- 3 files changed, 83 insertions(+), 22 deletions(-) diff --git a/config/phpstan-baseline.neon b/config/phpstan-baseline.neon index d5b49580..fa61d1ac 100644 --- a/config/phpstan-baseline.neon +++ b/config/phpstan-baseline.neon @@ -1,5 +1,11 @@ parameters: ignoreErrors: + - + rawMessage: Property APITester\Command\ExecutePlanCommand::$defaultName has no type specified. + identifier: missingType.property + count: 1 + path: ../src/Command/ExecutePlanCommand.php + - rawMessage: 'Method APITester\Config\Suite::getPreparators() should return array> but returns array.' identifier: return.type @@ -432,6 +438,36 @@ parameters: count: 1 path: ../src/Test/TestCase.php + - + rawMessage: 'Method APITester\Util\Assert::objectsEqual() throws checked exception Symfony\Component\Serializer\Exception\ExceptionInterface but it''s missing from the PHPDoc @throws tag.' + identifier: missingType.checkedException + count: 1 + path: ../src/Util/Assert.php + + - + rawMessage: 'Method APITester\Util\Json::deserialize() throws checked exception Symfony\Component\Serializer\Exception\ExceptionInterface but it''s missing from the PHPDoc @throws tag.' + identifier: missingType.checkedException + count: 1 + path: ../src/Util/Json.php + + - + rawMessage: 'Method APITester\Util\Json::serialize() throws checked exception Symfony\Component\Serializer\Exception\ExceptionInterface but it''s missing from the PHPDoc @throws tag.' + identifier: missingType.checkedException + count: 1 + path: ../src/Util/Json.php + + - + rawMessage: PHPDoc tag @param for parameter $format with type mixed is not subtype of native type string|null. + identifier: parameter.phpDocType + count: 2 + path: ../src/Util/Normalizer/PsrRequestNormalizer.php + + - + rawMessage: PHPDoc tag @param for parameter $format with type mixed is not subtype of native type string|null. + identifier: parameter.phpDocType + count: 2 + path: ../src/Util/Normalizer/PsrResponseNormalizer.php + - rawMessage: 'Call to method getTestName() of internal class PHPUnit\Framework\TestFailure from outside its root namespace PHPUnit.' identifier: method.internalClass @@ -468,6 +504,18 @@ parameters: count: 1 path: ../src/Util/TestCase/Printer/TestDoxPrinter.php + - + rawMessage: 'Method APITester\Util\Yaml::deserialize() throws checked exception Symfony\Component\Serializer\Exception\ExceptionInterface but it''s missing from the PHPDoc @throws tag.' + identifier: missingType.checkedException + count: 1 + path: ../src/Util/Yaml.php + + - + rawMessage: 'Method APITester\Util\Yaml::serialize() throws checked exception Symfony\Component\Serializer\Exception\ExceptionInterface but it''s missing from the PHPDoc @throws tag.' + identifier: missingType.checkedException + count: 1 + path: ../src/Util/Yaml.php + - rawMessage: Constructor of APITester\Config\Filters is invoked with named argument for parameter $include. identifier: ergebnis.noNamedArgument diff --git a/src/Util/Normalizer/PsrRequestNormalizer.php b/src/Util/Normalizer/PsrRequestNormalizer.php index 5d1463ea..65128eeb 100644 --- a/src/Util/Normalizer/PsrRequestNormalizer.php +++ b/src/Util/Normalizer/PsrRequestNormalizer.php @@ -14,10 +14,9 @@ final class PsrRequestNormalizer implements NormalizerInterface /** * @inerhitDoc * - * @param mixed $data * @param mixed|null $format */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof Request; } @@ -25,7 +24,6 @@ public function supportsNormalization($data, $format = null): bool /** * @inerhitDoc * - * @param mixed $object * @param mixed|null $format * * @return array{'method': string, @@ -34,16 +32,19 @@ public function supportsNormalization($data, $format = null): bool * 'headers': array * } */ - public function normalize($object, $format = null, array $context = []): array - { - /** @var Request $object */ + public function normalize( + mixed $data, + ?string $format = null, + array $context = [] + ): array { + /** @var Request $data */ $result = [ - 'method' => $object->getMethod(), - 'url' => (string) $object->getUri(), - 'body' => Json::isJson((string) $object->getBody()) ? Json::decode( - (string) $object->getBody() - ) : (string) $object->getBody(), - 'headers' => $object->getHeaders(), + 'method' => $data->getMethod(), + 'url' => (string) $data->getUri(), + 'body' => Json::isJson((string) $data->getBody()) ? Json::decode( + (string) $data->getBody() + ) : (string) $data->getBody(), + 'headers' => $data->getHeaders(), ]; if (isset($context[AbstractNormalizer::IGNORED_ATTRIBUTES])) { @@ -61,4 +62,11 @@ public function normalize($object, $format = null, array $context = []): array */ return $result; } + + public function getSupportedTypes(?string $format): array + { + return [ + Request::class => true, + ]; + } } diff --git a/src/Util/Normalizer/PsrResponseNormalizer.php b/src/Util/Normalizer/PsrResponseNormalizer.php index 2008e6dd..c886bfcb 100644 --- a/src/Util/Normalizer/PsrResponseNormalizer.php +++ b/src/Util/Normalizer/PsrResponseNormalizer.php @@ -14,10 +14,9 @@ final class PsrResponseNormalizer implements NormalizerInterface /** * @inerhitDoc * - * @param mixed $data * @param mixed|null $format */ - public function supportsNormalization($data, $format = null): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof Response; } @@ -25,7 +24,6 @@ public function supportsNormalization($data, $format = null): bool /** * @inerhitDoc * - * @param mixed $object * @param mixed|null $format * * @return array{ @@ -34,15 +32,15 @@ public function supportsNormalization($data, $format = null): bool * 'headers': array * } */ - public function normalize($object, $format = null, array $context = []): array + public function normalize(mixed $data, ?string $format = null, array $context = []): array { - /** @var Response $object */ + /** @var Response $data */ $result = [ - 'body' => Json::isJson((string) $object->getBody()) ? Json::decode( - (string) $object->getBody() - ) : (string) $object->getBody(), - 'headers' => $object->getHeaders(), - 'status' => $object->getStatusCode(), + 'body' => Json::isJson((string) $data->getBody()) ? Json::decode( + (string) $data->getBody() + ) : (string) $data->getBody(), + 'headers' => $data->getHeaders(), + 'status' => $data->getStatusCode(), ]; if (isset($context[AbstractNormalizer::IGNORED_ATTRIBUTES])) { @@ -60,4 +58,11 @@ public function normalize($object, $format = null, array $context = []): array */ return $result; } + + public function getSupportedTypes(?string $format): array + { + return [ + Response::class => true, + ]; + } } From 40ddd2ebf5fad02eac1491dc705d0b08763d2cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Fri, 30 Jan 2026 14:39:39 +0100 Subject: [PATCH 7/7] Restore vendors --- composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/composer.json b/composer.json index 9342fbd7..3d976f1a 100644 --- a/composer.json +++ b/composer.json @@ -51,12 +51,14 @@ "cebe/php-openapi": "^1.5", "fakerphp/faker": "^1.9", "firebase/php-jwt": "^6.0.0", + "guzzlehttp/promises": "^1.4.0", "illuminate/collections": "^11.0 || ^12.0", "league/openapi-psr7-validator": "^0.18", "myclabs/deep-copy": "^1.11", "nesbot/carbon": "^2.48", "nyholm/psr7": "1.*", "openclassrooms/openapi-psr7-validator": "dev-master", + "php-http/httplug": "^2.2", "opis/json-schema": "^2.3", "phpdocumentor/reflection-docblock": "^5.3", "phpstan/phpdoc-parser": "^1.2 || ^2.0",