Skip to content

Return the operation address even if request validation is skipped. #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2025
Merged
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
10 changes: 5 additions & 5 deletions src/ValidatesOpenApiSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ public function call($method, $uri, $parameters = [], $cookies = [], $files = []

$testResponse = $this->createTestResponse($response, $request);

if ($address) {
$this->validateResponse($address, $testResponse->baseResponse);
}
$this->validateResponse($address, $testResponse->baseResponse);

return $testResponse;
}
Expand Down Expand Up @@ -229,10 +227,12 @@ protected function getAuthenticatedRequest(SymfonyRequest $request): SymfonyRequ
/**
* Validates an HTTP Request
*/
protected function validateRequest(SymfonyRequest $request): ?OperationAddress
protected function validateRequest(SymfonyRequest $request): OperationAddress
{
if ($this->shouldSkipRequestValidation()) {
return null;
$psr7Request = $this->getPsr7Factory()->createRequest($request);

return new OperationAddress($psr7Request->getUri()->getPath(), strtolower($request->getMethod()));
}

$authenticatedRequest = $this->getAuthenticatedRequest($request);
Expand Down
151 changes: 151 additions & 0 deletions tests/ValidatesRequestsWithSkipTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

namespace Kirschbaum\OpenApiValidator\Tests;

use Exception;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Kirschbaum\OpenApiValidator\ValidatesOpenApiSpec;
use League\OpenAPIValidation\PSR7\Exception\NoPath;
use League\OpenAPIValidation\PSR7\OperationAddress;
use Orchestra\Testbench\TestCase;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;

class ValidatesRequestsWithSkipTest extends TestCase
{
use ValidatesOpenApiSpec;
use WithFaker;

protected function setUp(): void
{
parent::setUp();

$this->app['config']->set('openapi_validator.spec_path', __DIR__.'/fixtures/OpenAPI.yaml');
}

/**
* @test
* @dataProvider provideValidationScenarios
*/
public function testValidatesRequests(array $requestData, bool $expectSuccess, ?string $expectedException = null)
{
extract($requestData);

$request = $this->makeRequest($method, $uri, $parameters ?? [], $cookies ?? [], $files ?? [], $server ?? [], $content ?? null);

try {
$result = $this->validateRequest($request);
} catch (Exception $exception) {
if (is_null($expectedException)) {
$this->fail('Validation failed with unexpected exception ' . get_class($exception) . PHP_EOL . $exception->getMessage());
}
$this->assertInstanceOf($expectedException, $exception, "Expected an exception of class [{$expectedException}] to be thrown, got " . get_class($exception));

$this->assertFalse($expectSuccess);
// End the test here
return;
}

$this->assertTrue($expectSuccess, 'Not expecting a successful validation, but here we are...');

$this->assertInstanceOf(OperationAddress::class, $result);
$this->assertTrue(OperationAddress::isPathMatchesSpec($result->path(), Str::start($uri, '/')), 'Spec path does not match given path.');
$this->assertEqualsIgnoringCase($method, $result->method());
}

/**
* Provides a handful of scenarios to test the validator is hooked up correctly.
* We'll defer the actual testing to the league's validator itself.
*/
public static function provideValidationScenarios()
{
yield 'Gets test OK' => [
[
'method' => 'GET',
'uri' => 'test',
],
true,
];

yield 'Gets params with param' => [
[
'method' => 'GET',
'uri' => 'params/parameter1',
],
true,
];

yield 'Fails to gets params without param' => [
[
'method' => 'GET',
'uri' => 'params',
],
true,
NoPath::class,
];

yield 'Gets query with query params' => [
[
'method' => 'GET',
'uri' => 'query-params',
'parameters' => ['parameter' => 'forks'],
],
true,
];

yield 'Fails to get query with query params in path' => [
[
'method' => 'GET',
'uri' => 'query-params/forks',
],
true,
NoPath::class,
];

yield 'Posts with form' => [
[
'method' => 'POST',
'uri' => 'form',
'content' => json_encode([
'formInputInteger' => 14,
'formInputString' => 'yarn',
]),
'server' => ['CONTENT_TYPE' => 'application/json'],
],
true,
];

yield 'Authentication required' => [
[
'method' => 'GET',
'uri' => 'private',
'server' => ['HTTP_Authorization' => 'Basic MTIzNDU2Nzg5MDo='],
],
true,
];
}

private function makeRequest($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
$symfonyRequest = SymfonyRequest::create(
$this->prepareUrlForRequest($uri),
$method,
$parameters,
$cookies,
$files,
array_replace($this->serverVariables, $server),
$content
);

return Request::createFromBase($symfonyRequest);
}

/**
* NOTE: overriding this method for testing
*/
public function shouldSkipRequestValidation()
{
return true;
}
}