Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 25 additions & 41 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,59 +51,48 @@
"cebe/php-openapi": "^1.5",
"fakerphp/faker": "^1.9",
"firebase/php-jwt": "^6.0.0",
"guzzlehttp/promises": "^1.4.0",
"illuminate/collections": "^8.0",
"monolog/monolog": "^1.25.1 || ^2.8.0 || ^3.0.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.*",
"league/openapi-psr7-validator": "^0.18",
"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",
"phpstan/phpdoc-parser": "^1.2 || ^2.0",
"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",
"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",
"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",
"thecodingmachine/phpstan-strict-rules": "^1.0",
"veewee/composer-run-parallel": "^1.1"
"spaze/phpstan-disallowed-calls": "^4.7",
"symfony/var-dumper": "^5.0 || ^6.0 || ^7.0",
"symplify/easy-coding-standard": "^11.3"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/sidux/collections"
},
{
"type": "vcs",
"url": "https://github.com/OpenClassrooms/openapi-psr7-validator"
Expand All @@ -116,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"
],
Expand Down
519 changes: 499 additions & 20 deletions config/phpstan-baseline.neon

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions config/phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -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\(\)/'}
Expand Down
2 changes: 1 addition & 1 deletion src/Config/Loader/PlanConfigLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Config/Suite.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 2 additions & 4 deletions src/Definition/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,8 @@ public function setTags(Tags $tags): self
*/
public function getScopes(): Collection
{
/** @var Collection<array-key, string> */
return $this->getSecurities()
->select('scopes')
->pluck('scopes')
->flatten()
->unique()
;
Expand All @@ -117,9 +116,8 @@ public function getScopes(): Collection
*/
public function getSecurities(): Collection
{
/** @var Collection<array-key, Security> */
return $this->getOperations()
->select('securities.*')
->pluck('securities.*')
->flatten()
;
}
Expand Down
13 changes: 4 additions & 9 deletions src/Definition/Body.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

final class Body
{
private Operation $parent;
public readonly Schema $schema;

private readonly Schema $schema;
public bool $required = false;

private bool $required = false;
private Operation $parent;

/**
* @param Schema|array<mixed> $schema
Expand All @@ -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);
}
Expand All @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions src/Definition/Collection/Comparable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace APITester\Definition\Collection;

trait Comparable
{
/**
* @param iterable<array-key, TValue> $items
*
* @return static<TKey, TValue>
*/
public function compare(iterable $items): self
{
return $this->diff($items)
->merge(collect($items)->diff($this))
;
}
}
2 changes: 1 addition & 1 deletion src/Definition/Collection/OperationExamples.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class OperationExamples extends Collection
/**
* @var OperationExample[]
*/
protected array $examples;
public array $examples;

/**
* @param OperationExample[] $examples
Expand Down
5 changes: 3 additions & 2 deletions src/Definition/Collection/Operations.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

/**
* @method Operation[] getIterator()
* @method Operations map(callable $c)
* @extends Collection<array-key, Operation>
*/
final class Operations extends Collection
{
use Comparable;

/**
* @return array<string, array<Operation>>
*/
Expand All @@ -23,7 +24,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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Definition/Collection/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final class Parameters extends Collection
/**
* @var Parameter[]
*/
protected $items;
public $items;

/**
* @return array<string, string|int>
Expand Down
2 changes: 1 addition & 1 deletion src/Definition/Collection/Responses.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

/**
* @method Response[] getIterator()
* @method Responses map(callable $c)
* @extends Collection<array-key, Response>
*/
final class Responses extends Collection
{
use Comparable;
}
10 changes: 5 additions & 5 deletions src/Definition/Example/OperationExample.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
) {
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -380,7 +378,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()
;

Expand All @@ -392,7 +390,9 @@ 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(
static fn (Token $t) => count(array_diff($scopes, $t->getScopes())) === 0
)
->first()
;
}
Expand Down
10 changes: 5 additions & 5 deletions src/Definition/Loader/OpenApiDefinitionLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
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;
use Psr\Log\NullLogger;
Expand Down Expand Up @@ -117,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 ?? []);
$requirements = $this->getSecurityRequirementsScopes(
$operation->security ?? new SecurityRequirements([])
);

$operations->add(
Operation::create(
Expand Down Expand Up @@ -174,11 +176,9 @@ private function getTags(array $tags): Tags
}

/**
* @param SecurityRequirement[] $securityRequirements
*
* @return array<string, string[]>
*/
private function getSecurityRequirementsScopes(array $securityRequirements): array
private function getSecurityRequirementsScopes(SecurityRequirements $securityRequirements): array
{
$requirements = [];
foreach ($securityRequirements as $requirement) {
Expand Down
Loading