Skip to content

Commit

Permalink
Add 403UserCentricPreparator to handle random parameters that generat…
Browse files Browse the repository at this point in the history
…es a 403 error because the user is not allowed to browse them
  • Loading branch information
Wilkins committed Feb 1, 2024
1 parent 8d2b024 commit bdd741f
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/Definition/Loader/OpenApiDefinitionLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use cebe\openapi\spec\MediaType;
use cebe\openapi\spec\OAuthFlow;
use cebe\openapi\spec\OpenApi;
use cebe\openapi\spec\Operation as OpenApiOperation;
use cebe\openapi\spec\PathItem;
use cebe\openapi\spec\RequestBody;
use cebe\openapi\spec\Schema;
Expand Down Expand Up @@ -115,13 +116,23 @@ private function getOperations(array $paths, array $securitySchemes): Operations
->setTags($this->getTags($operation->tags))
->setSecurities($this->getSecurities($securitySchemes, $requirements))
->setExamples($this->getExamples($operation, $parameters))
->setCustomParameters($this->getCustomParameters($operation))
);
}
}

return $operations;
}

private function getCustomParameters(OpenApiOperation $operation): array

Check failure on line 127 in src/Definition/Loader/OpenApiDefinitionLoader.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method APITester\Definition\Loader\OpenApiDefinitionLoader::getCustomParameters() return type has no value type specified in iterable type array.
{
return array_filter(
(array) $operation->getSerializableData(),
fn ($v, $k) => str_starts_with($k, 'x-'),
ARRAY_FILTER_USE_BOTH
);
}

/**
* @param \cebe\openapi\spec\Server[] $servers
*/
Expand Down
20 changes: 20 additions & 0 deletions src/Definition/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ final class Operation implements Filterable

private OperationExamples $examples;

private array $customParameters;

Check failure on line 46 in src/Definition/Operation.php

View workflow job for this annotation

GitHub Actions / PHPStan

Property APITester\Definition\Operation::$customParameters type has no value type specified in iterable type array.

public function __construct(
private readonly string $id,
private readonly string $path,
Expand All @@ -56,6 +58,7 @@ public function __construct(
$this->tags = new Tags();
$this->securities = new Securities();
$this->examples = new OperationExamples();
$this->customParameters = [];
}

public function addHeader(Parameter $header): self
Expand Down Expand Up @@ -277,6 +280,23 @@ public function setExamples(OperationExamples $examples): self
return $this;
}

public function getCustomParameters(): array

Check failure on line 283 in src/Definition/Operation.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method APITester\Definition\Operation::getCustomParameters() return type has no value type specified in iterable type array.
{
return $this->customParameters;
}

public function setCustomParameters(array $customParameters): self

Check failure on line 288 in src/Definition/Operation.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method APITester\Definition\Operation::setCustomParameters() has parameter $customParameters with no value type specified in iterable type array.
{
$this->customParameters = $customParameters;

return $this;
}

public function isUserCentric(): bool
{
return isset($this->customParameters['x-apitester-user-centric-parameter']) && $this->customParameters['x-apitester-user-centric-parameter'] === true;
}

/**
* @param array<int|string, string|int> $params
*
Expand Down
71 changes: 71 additions & 0 deletions src/Preparator/Error403UserCentricPreparator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace APITester\Preparator;

use APITester\Definition\Collection\Operations;
use APITester\Definition\Example\OperationExample;
use APITester\Definition\Example\ResponseExample;
use APITester\Definition\Operation;
use APITester\Definition\Response as DefinitionResponse;
use APITester\Test\TestCase;

final class Error403UserCentricPreparator extends TestCasesPreparator
{
public function getStatusCode(): string
{
return '403';
}
/**
* @inheritDoc
*/
protected function prepare(Operations $operations): iterable
{
/** @var iterable<array-key, TestCase> */
return $operations
->filter(fn ($operation) => $operation->isUserCentric())
->values()
->map(function ($operation) {
return $this->prepareTestCase($operation);
})
->flatten()
;
}

/**
* @return array<TestCase>
*/
private function prepareTestCase(Operation $operation): array
{
$testcases = [];

if ($operation->getRequestBodies()->count() === 0) {
$testcases[] = $this->buildTestCase(
OperationExample::create('RandomPath', $operation)
->setForceRandom()
->setResponse(
ResponseExample::create()
->setStatusCode($this->config->response->getStatusCode() ?? '403')
->setHeaders($this->config->response->headers ?? [])
->setContent($this->config->response->body ?? null)
)
);
}

foreach ($operation->getRequestBodies() as $ignored) {
$testcases[] = $this->buildTestCase(
OperationExample::create('RandomPath', $operation)
->setForceRandom()
->setResponse(
ResponseExample::create()
->setStatusCode($this->config->response->getStatusCode() ?? '403')
->setHeaders($this->config->response->headers ?? [])
->setContent($this->config->response->body ?? null)
)
);
}

return $testcases;
}
}
11 changes: 8 additions & 3 deletions src/Preparator/Error404Preparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

final class Error404Preparator extends TestCasesPreparator
{
protected function getStatusCode(): string

Check failure on line 15 in src/Preparator/Error404Preparator.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method APITester\Preparator\Error404Preparator::getStatusCode() is protected, but since the containing class is final, it can be private.
{
return '404';
}
/**
* @inheritDoc
*/
Expand All @@ -21,7 +25,8 @@ protected function prepare(Operations $operations): iterable
return $operations
->select('responses.*')
->flatten()
->where('statusCode', 404)
->where('statusCode', $this->getStatusCode())
->filter(fn ($response) => !$response->getParent()->isUserCentric())

Check failure on line 29 in src/Preparator/Error404Preparator.php

View workflow job for this annotation

GitHub Actions / PHPStan

Cannot call method getParent() on mixed.
->values()
->map(function ($response) {
/** @var DefinitionResponse $response */
Expand All @@ -46,7 +51,7 @@ private function prepareTestCase(DefinitionResponse $response): array
->setForceRandom()
->setResponse(
ResponseExample::create()
->setStatusCode($this->config->response->getStatusCode() ?? '404')
->setStatusCode($this->config->response->getStatusCode() ?? $this->getStatusCode())
->setHeaders($this->config->response->headers ?? [])
->setContent($this->config->response->body ?? $response->getDescription())
)
Expand All @@ -59,7 +64,7 @@ private function prepareTestCase(DefinitionResponse $response): array
->setForceRandom()
->setResponse(
ResponseExample::create()
->setStatusCode($this->config->response->getStatusCode() ?? '404')
->setStatusCode($this->config->response->getStatusCode() ?? $this->getStatusCode())
->setHeaders($this->config->response->headers ?? [])
->setContent($this->config->response->body ?? $response->getDescription())
)
Expand Down

0 comments on commit bdd741f

Please sign in to comment.