Skip to content

Commit 4a3d0dd

Browse files
authored
Return the operation address even if request validation is skipped. (#26)
1 parent fd989b4 commit 4a3d0dd

File tree

2 files changed

+156
-5
lines changed

2 files changed

+156
-5
lines changed

src/ValidatesOpenApiSpec.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ public function call($method, $uri, $parameters = [], $cookies = [], $files = []
9494

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

97-
if ($address) {
98-
$this->validateResponse($address, $testResponse->baseResponse);
99-
}
97+
$this->validateResponse($address, $testResponse->baseResponse);
10098

10199
return $testResponse;
102100
}
@@ -229,10 +227,12 @@ protected function getAuthenticatedRequest(SymfonyRequest $request): SymfonyRequ
229227
/**
230228
* Validates an HTTP Request
231229
*/
232-
protected function validateRequest(SymfonyRequest $request): ?OperationAddress
230+
protected function validateRequest(SymfonyRequest $request): OperationAddress
233231
{
234232
if ($this->shouldSkipRequestValidation()) {
235-
return null;
233+
$psr7Request = $this->getPsr7Factory()->createRequest($request);
234+
235+
return new OperationAddress($psr7Request->getUri()->getPath(), strtolower($request->getMethod()));
236236
}
237237

238238
$authenticatedRequest = $this->getAuthenticatedRequest($request);
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
namespace Kirschbaum\OpenApiValidator\Tests;
4+
5+
use Exception;
6+
use Illuminate\Foundation\Testing\WithFaker;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Str;
9+
use Kirschbaum\OpenApiValidator\ValidatesOpenApiSpec;
10+
use League\OpenAPIValidation\PSR7\Exception\NoPath;
11+
use League\OpenAPIValidation\PSR7\OperationAddress;
12+
use Orchestra\Testbench\TestCase;
13+
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
14+
15+
class ValidatesRequestsWithSkipTest extends TestCase
16+
{
17+
use ValidatesOpenApiSpec;
18+
use WithFaker;
19+
20+
protected function setUp(): void
21+
{
22+
parent::setUp();
23+
24+
$this->app['config']->set('openapi_validator.spec_path', __DIR__.'/fixtures/OpenAPI.yaml');
25+
}
26+
27+
/**
28+
* @test
29+
* @dataProvider provideValidationScenarios
30+
*/
31+
public function testValidatesRequests(array $requestData, bool $expectSuccess, ?string $expectedException = null)
32+
{
33+
extract($requestData);
34+
35+
$request = $this->makeRequest($method, $uri, $parameters ?? [], $cookies ?? [], $files ?? [], $server ?? [], $content ?? null);
36+
37+
try {
38+
$result = $this->validateRequest($request);
39+
} catch (Exception $exception) {
40+
if (is_null($expectedException)) {
41+
$this->fail('Validation failed with unexpected exception ' . get_class($exception) . PHP_EOL . $exception->getMessage());
42+
}
43+
$this->assertInstanceOf($expectedException, $exception, "Expected an exception of class [{$expectedException}] to be thrown, got " . get_class($exception));
44+
45+
$this->assertFalse($expectSuccess);
46+
// End the test here
47+
return;
48+
}
49+
50+
$this->assertTrue($expectSuccess, 'Not expecting a successful validation, but here we are...');
51+
52+
$this->assertInstanceOf(OperationAddress::class, $result);
53+
$this->assertTrue(OperationAddress::isPathMatchesSpec($result->path(), Str::start($uri, '/')), 'Spec path does not match given path.');
54+
$this->assertEqualsIgnoringCase($method, $result->method());
55+
}
56+
57+
/**
58+
* Provides a handful of scenarios to test the validator is hooked up correctly.
59+
* We'll defer the actual testing to the league's validator itself.
60+
*/
61+
public static function provideValidationScenarios()
62+
{
63+
yield 'Gets test OK' => [
64+
[
65+
'method' => 'GET',
66+
'uri' => 'test',
67+
],
68+
true,
69+
];
70+
71+
yield 'Gets params with param' => [
72+
[
73+
'method' => 'GET',
74+
'uri' => 'params/parameter1',
75+
],
76+
true,
77+
];
78+
79+
yield 'Fails to gets params without param' => [
80+
[
81+
'method' => 'GET',
82+
'uri' => 'params',
83+
],
84+
true,
85+
NoPath::class,
86+
];
87+
88+
yield 'Gets query with query params' => [
89+
[
90+
'method' => 'GET',
91+
'uri' => 'query-params',
92+
'parameters' => ['parameter' => 'forks'],
93+
],
94+
true,
95+
];
96+
97+
yield 'Fails to get query with query params in path' => [
98+
[
99+
'method' => 'GET',
100+
'uri' => 'query-params/forks',
101+
],
102+
true,
103+
NoPath::class,
104+
];
105+
106+
yield 'Posts with form' => [
107+
[
108+
'method' => 'POST',
109+
'uri' => 'form',
110+
'content' => json_encode([
111+
'formInputInteger' => 14,
112+
'formInputString' => 'yarn',
113+
]),
114+
'server' => ['CONTENT_TYPE' => 'application/json'],
115+
],
116+
true,
117+
];
118+
119+
yield 'Authentication required' => [
120+
[
121+
'method' => 'GET',
122+
'uri' => 'private',
123+
'server' => ['HTTP_Authorization' => 'Basic MTIzNDU2Nzg5MDo='],
124+
],
125+
true,
126+
];
127+
}
128+
129+
private function makeRequest($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
130+
{
131+
$symfonyRequest = SymfonyRequest::create(
132+
$this->prepareUrlForRequest($uri),
133+
$method,
134+
$parameters,
135+
$cookies,
136+
$files,
137+
array_replace($this->serverVariables, $server),
138+
$content
139+
);
140+
141+
return Request::createFromBase($symfonyRequest);
142+
}
143+
144+
/**
145+
* NOTE: overriding this method for testing
146+
*/
147+
public function shouldSkipRequestValidation()
148+
{
149+
return true;
150+
}
151+
}

0 commit comments

Comments
 (0)