diff --git a/src/ValidatesOpenApiSpec.php b/src/ValidatesOpenApiSpec.php index a987e71..ff3cedc 100644 --- a/src/ValidatesOpenApiSpec.php +++ b/src/ValidatesOpenApiSpec.php @@ -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; } @@ -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); diff --git a/tests/ValidatesRequestsWithSkipTest.php b/tests/ValidatesRequestsWithSkipTest.php new file mode 100644 index 0000000..f7d03dd --- /dev/null +++ b/tests/ValidatesRequestsWithSkipTest.php @@ -0,0 +1,151 @@ +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; + } +}