Skip to content

Commit

Permalink
Skip request validation (#110)
Browse files Browse the repository at this point in the history
Cache exceptions for selective reporting
  • Loading branch information
hotmeteor authored Aug 8, 2022
1 parent b4d1101 commit aae40bb
Show file tree
Hide file tree
Showing 11 changed files with 376 additions and 278 deletions.
27 changes: 15 additions & 12 deletions _ide_helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
/**
* @see \Spectator\Assertions
*
* @method self assertValidRequest()
* @method self assertInvalidRequest()
* @method self assertValidResponse($status = null)
* @method self assertInvalidResponse($status = null)
* @method self assertValidationMessage($expected)
* @method self assertErrorsContain($errors)
* @method static assertValidRequest()
* @method static assertInvalidRequest()
* @method static assertValidResponse($status = null)
* @method static assertInvalidResponse($status = null)
* @method static assertValidationMessage($expected)
* @method static assertErrorsContain($errors)
* @method static dumpSpecErrors()
* @method static void skipRequestValidation()
*/
class TestResponse
{
Expand All @@ -27,12 +29,13 @@ class TestResponse
/**
* @see \Spectator\Assertions
*
* @method self assertValidRequest()
* @method self assertInvalidRequest()
* @method self assertValidResponse($status = null)
* @method self assertInvalidResponse($status = null)
* @method self assertValidationMessage($expected)
* @method self assertErrorsContain($errors)
* @method static assertValidRequest()
* @method static assertInvalidRequest()
* @method static assertValidResponse($status = null)
* @method static assertInvalidResponse($status = null)
* @method static assertValidationMessage($expected)
* @method static assertErrorsContain($errors)
* @method static void skipRequestValidation()
*/
class TestResponse
{
Expand Down
218 changes: 124 additions & 94 deletions src/Assertions.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
use cebe\openapi\exceptions\TypeErrorException;
use cebe\openapi\exceptions\UnresolvableReferenceException;
use Closure;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use PHPUnit\Framework\Assert as PHPUnit;
use Spectator\Concerns\HasExpectations;
use Spectator\Exceptions\InvalidPathException;
use Spectator\Exceptions\MalformedSpecException;
use Spectator\Exceptions\MissingSpecException;
use Spectator\Exceptions\RequestValidationException;
use Spectator\Exceptions\ResponseValidationException;
Expand All @@ -22,121 +23,134 @@ class Assertions

public function assertValidRequest()
{
return function () {
return $this->runAssertion(function () {
$contents = $this->getContent() ? $contents = (array) $this->json() : [];

$this->expectsFalse($contents, [
InvalidPathException::class,
MissingSpecException::class,
RequestValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

return $this;
});
};
return fn () => $this->runAssertion(function () {
$exception = app('spectator')->requestException;

$this->expectsFalse($exception, [
InvalidPathException::class,
MalformedSpecException::class,
MissingSpecException::class,
RequestValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

return $this;
});
}

public function assertInvalidRequest()
{
return function () {
return $this->runAssertion(function () {
$contents = (array) $this->json();

$this->expectsTrue($contents, [
InvalidPathException::class,
MissingSpecException::class,
RequestValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

return $this;
});
};
return fn () => $this->runAssertion(function () {
$exception = app('spectator')->requestException;

$this->expectsTrue($exception, [
InvalidPathException::class,
MalformedSpecException::class,
MissingSpecException::class,
RequestValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

return $this;
});
}

public function assertValidResponse()
{
return function ($status = null) {
return $this->runAssertion(function () use ($status) {
$contents = $this->getContent() ? (array) $this->json() : [];

$this->expectsFalse($contents, [
ResponseValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

if ($status) {
$actual = $this->getStatusCode();

PHPUnit::assertTrue(
$actual === $status,
"Expected status code {$status} but received {$actual}."
);
}
return fn ($status = null) => $this->runAssertion(function () use ($status) {
$exception = app('spectator')->responseException;

return $this;
});
};
$this->expectsFalse($exception, [
ResponseValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

if ($status) {
$actual = $this->getStatusCode();

PHPUnit::assertTrue(
$actual === $status,
"Expected status code {$status} but received {$actual}."
);
}

return $this;
});
}

public function assertInvalidResponse()
{
return function ($status = null) {
return $this->runAssertion(function () use ($status) {
$contents = (array) $this->json();

$this->expectsTrue($contents, [
ResponseValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

if ($status) {
$actual = $this->getStatusCode();

PHPUnit::assertTrue(
$actual === $status,
"Expected status code {$status} but received {$actual}."
);
}
return fn ($status = null) => $this->runAssertion(function () use ($status) {
$exception = app('spectator')->responseException;

return $this;
});
};
$this->expectsTrue($exception, [
ResponseValidationException::class,
TypeErrorException::class,
UnresolvableReferenceException::class,
]);

if ($status) {
$actual = $this->getStatusCode();

PHPUnit::assertTrue(
$actual === $status,
"Expected status code {$status} but received {$actual}."
);
}

return $this;
});
}

public function assertValidationMessage()
{
return function ($expected) {
return $this->runAssertion(function () use ($expected) {
$actual = $this->decodeExceptionMessage((array) $this->json());

PHPUnit::assertStringContainsString(
$expected,
$actual,
'The expected error did not match the actual error.'
);

return $this;
});
};
return fn ($expected) => $this->runAssertion(function () use ($expected) {
PHPUnit::assertStringContainsString(
$expected,
implode(' ', $this->collectExceptionMessages()),
'The expected error did not match the actual error.'
);

return $this;
});
}

public function assertErrorsContain()
{
return function ($errors) {
return $this->runAssertion(function () use ($errors) {
self::assertJson([
'specErrors' => Arr::wrap($errors),
]);

return $this;
});
return fn ($errors) => $this->runAssertion(function () use ($errors) {
$matches = 0;

if (! is_array($errors)) {
$errors = [$errors];
}

foreach ($errors as $error) {
foreach ($this->collectExceptionMessages() as $message) {
if (Str::contains($message, $error)) {
$matches++;
}
}
}

PHPUnit::assertNotSame(
0,
$matches,
'The expected error was not found.'
);

return $this;
});
}

public function dumpSpecErrors()
{
return function () {
dump($this->collectExceptionMessages());

return $this;
};
}

Expand All @@ -152,4 +166,20 @@ protected function runAssertion()
}
};
}

protected function collectExceptionMessages()
{
/*
* @return array
*/
return function (): array {
$requestException = app('spectator')->requestException;
$responseException = app('spectator')->responseException;

return array_filter([
$requestException ? urldecode($requestException->getMessage()) : null,
$responseException ? urldecode($responseException->getMessage()) : null,
]);
};
}
}
Loading

0 comments on commit aae40bb

Please sign in to comment.