diff --git a/src/Command/ExecutePlanCommand.php b/src/Command/ExecutePlanCommand.php index 7b8fae8..8aaff63 100644 --- a/src/Command/ExecutePlanCommand.php +++ b/src/Command/ExecutePlanCommand.php @@ -177,6 +177,12 @@ protected function configure(): void InputOption::VALUE_OPTIONAL, 'Partition tests into groups and run only one of them, ex: --part=1/3' ) + ->addOption( + 'operation-id', + null, + InputOption::VALUE_OPTIONAL, + 'takes an operation-id to load from api definition' + ) ; } diff --git a/src/Definition/Example/OperationExample.php b/src/Definition/Example/OperationExample.php index 8cbc6ad..497fd67 100644 --- a/src/Definition/Example/OperationExample.php +++ b/src/Definition/Example/OperationExample.php @@ -357,7 +357,7 @@ public function setForceRandom(bool $forceRandom = true): self return $this; } - public function authenticate(Tokens $tokens, bool $ignoreScope = false): self + public function setAuthenticationHeaders(Tokens $tokens, bool $ignoreScope = false): self { $operation = $this->getParent(); if ($operation === null) { diff --git a/src/Definition/Loader/DefinitionLoader.php b/src/Definition/Loader/DefinitionLoader.php index b4fb401..54a1fe8 100644 --- a/src/Definition/Loader/DefinitionLoader.php +++ b/src/Definition/Loader/DefinitionLoader.php @@ -10,12 +10,20 @@ interface DefinitionLoader { + public const FORMAT_JSON = 'json'; + + public const FORMAT_YAML = 'yaml'; + + public const FORMATS = [self::FORMAT_JSON, self::FORMAT_YAML]; + public static function getFormat(): string; public function setLogger(LoggerInterface $logger): void; /** + * @param array $filters + * * @throws DefinitionLoadingException */ - public function load(string $filePath): Api; + public function load(string $filePath, string $format = self::FORMAT_YAML, array $filters = []): Api; } diff --git a/src/Definition/Loader/OpenApiDefinitionLoader.php b/src/Definition/Loader/OpenApiDefinitionLoader.php index 2b091ce..d36fcbc 100644 --- a/src/Definition/Loader/OpenApiDefinitionLoader.php +++ b/src/Definition/Loader/OpenApiDefinitionLoader.php @@ -48,12 +48,6 @@ final class OpenApiDefinitionLoader implements DefinitionLoader { - public const FORMAT_JSON = 'json'; - - public const FORMAT_YAML = 'yaml'; - - public const FORMATS = [self::FORMAT_JSON, self::FORMAT_YAML]; - private LoggerInterface $logger; public function __construct(?LoggerInterface $logger = null) @@ -61,10 +55,7 @@ public function __construct(?LoggerInterface $logger = null) $this->logger = $logger ?? new NullLogger(); } - /** - * @throws DefinitionLoadingException - */ - public function load(string $filePath, string $format = self::FORMAT_YAML): Api + public function load(string $filePath, string $format = self::FORMAT_YAML, array $filters = []): Api { $api = Api::create(); if (!\in_array($format, self::FORMATS, true)) { @@ -81,7 +72,13 @@ public function load(string $filePath, string $format = self::FORMAT_YAML): Api $securitySchemes = $openApi->components !== null ? $openApi->components->securitySchemes : []; return $api - ->setOperations($this->getOperations($openApi->paths->getPaths(), $securitySchemes)) + ->setOperations( + $this->getOperations( + $openApi->paths->getPaths(), + $securitySchemes, + $filters + ) + ) ->setServers($this->getServers($openApi->servers)) ->setTags($this->getTags($openApi->tags)) ; @@ -98,16 +95,21 @@ public function setLogger(LoggerInterface $logger): void } /** + * @param array $filters * @param array $securitySchemes * @param array $paths * * @throws DefinitionLoadingException */ - private function getOperations(array $paths, array $securitySchemes): Operations + private function getOperations(array $paths, array $securitySchemes, array $filters = []): Operations { $operations = new Operations(); foreach ($paths as $path => $pathInfo) { foreach ($pathInfo->getOperations() as $method => $operation) { + if (isset($filters['operationId']) + && !in_array($operation->operationId, $filters['operationId'], true)) { + continue; + } /** @var \cebe\openapi\spec\Parameter[] $parameters */ $parameters = array_merge($operation->parameters ?? [], $pathInfo->parameters ?? []); /** @var RequestBody $requestBody */ diff --git a/src/Preparator/SecurityErrorPreparator.php b/src/Preparator/SecurityErrorPreparator.php index c14550a..ff056b5 100644 --- a/src/Preparator/SecurityErrorPreparator.php +++ b/src/Preparator/SecurityErrorPreparator.php @@ -55,7 +55,7 @@ private function prepareTestCases(Security $security): iterable $testCases->add( $this->buildTestCase( OperationExample::create($this->getTestCaseName(), $operation) - ->authenticate(new Tokens([$token]), true) + ->setAuthenticationHeaders(new Tokens([$token]), true) ->setResponse(ResponseExample::create()->setStatusCode($this->getStatusCode())), false, ), @@ -65,7 +65,7 @@ private function prepareTestCases(Security $security): iterable $testCases->add( $this->buildTestCase( OperationExample::create($this->getTestCaseName(), $operation) - ->authenticate(new Tokens([$token]), true) + ->setAuthenticationHeaders(new Tokens([$token]), true) ->setResponse(ResponseExample::create()->setStatusCode($this->getStatusCode())), false, ), diff --git a/src/Preparator/TestCasesPreparator.php b/src/Preparator/TestCasesPreparator.php index ffc00ac..60508cf 100644 --- a/src/Preparator/TestCasesPreparator.php +++ b/src/Preparator/TestCasesPreparator.php @@ -43,7 +43,7 @@ final public function buildTestCase( $operation = $example->getParent(); if ($auth) { - $example->authenticate($this->tokens); + $example->setAuthenticationHeaders($this->tokens); } return new TestCase( diff --git a/src/Test/Plan.php b/src/Test/Plan.php index 411405b..35dc623 100644 --- a/src/Test/Plan.php +++ b/src/Test/Plan.php @@ -119,7 +119,7 @@ public function execute( if (!empty($options['set-baseline'])) { $this->resetBaseLine($suiteConfig); } - $testSuite = $this->prepareSuite($suiteConfig); + $testSuite = $this->prepareSuite($suiteConfig, $options); if (!empty($options['ignore-baseline'])) { $testSuite->setIgnoreBaseLine(true); } @@ -185,6 +185,8 @@ private function resetBaseLine(Config\Suite $suiteConfig): void } /** + * @param array $options + * * @throws AuthenticationException * @throws AuthenticationLoadingException * @throws DefinitionLoaderNotFoundException @@ -194,14 +196,14 @@ private function resetBaseLine(Config\Suite $suiteConfig): void * * @return Suite<\PHPUnit\Framework\TestCase, HttpKernelInterface> */ - private function prepareSuite(Config\Suite $suiteConfig): Suite + private function prepareSuite(Config\Suite $suiteConfig, array $options = []): Suite { $testCaseClass = Object_::validateClass( $suiteConfig->getTestCaseClass(), \PHPUnit\Framework\TestCase::class ); $kernel = $this->loadSymfonyKernel($suiteConfig, $testCaseClass); - $definition = $this->loadApiDefinition($suiteConfig); + $definition = $this->loadApiDefinition($suiteConfig, $options); $requester = $this->loadRequester( $suiteConfig->getRequester(), $suiteConfig->getBaseUrl() ?? $definition->getUrl(), @@ -295,19 +297,30 @@ private function loadSymfonyKernel(Config\Suite $suiteConfig, string $testCaseCl } /** + * @param array $options + * * @throws DefinitionLoaderNotFoundException * @throws DefinitionLoadingException */ - private function loadApiDefinition(Config\Suite $config): Api + private function loadApiDefinition(Config\Suite $config, array $options = []): Api { $definitionLoader = $this->getConfiguredLoader( $config->getDefinition() ->getFormat() ); + $filters = []; + if (isset($options['operation-id'])) { + $filters['operationId'] = array_map( + 'trim', + explode(',', (string) $options['operation-id']) + ); + } + return $definitionLoader->load( $config->getDefinition() - ->getPath() + ->getPath(), + filters: $filters, ); }