Skip to content
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

[5.8] Add message value assertion to assertJsonValidationErrors #27655

Closed
wants to merge 9 commits into from
Closed
37 changes: 23 additions & 14 deletions src/Illuminate/Foundation/Testing/TestResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -631,30 +631,39 @@ public function assertJsonCount(int $count, $key = null)
}

/**
* Assert that the response has the given JSON validation errors for the given keys.
* Assert that the response has the given JSON validation errors.
*
* @param string|array $keys
* @param string|array $errors
* @return $this
*/
public function assertJsonValidationErrors($keys)
public function assertJsonValidationErrors($errors)
{
$keys = Arr::wrap($keys);
$errors = Arr::wrap($errors);

PHPUnit::assertNotEmpty($keys, 'No keys were provided.');
PHPUnit::assertNotEmpty($errors, 'No validation errors were provided.');

$errors = $this->json()['errors'] ?? [];
$jsonErrors = $this->json()['errors'] ?? [];

$errorMessage = $errors
$errorMessage = $jsonErrors
? 'Response has the following JSON validation errors:'.
PHP_EOL.PHP_EOL.json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL
PHP_EOL.PHP_EOL.json_encode($jsonErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL
: 'Response does not have JSON validation errors.';

foreach ($keys as $key) {
PHPUnit::assertArrayHasKey(
$key,
$errors,
"Failed to find a validation error in the response for key: '{$key}'".PHP_EOL.PHP_EOL.$errorMessage
);
foreach ($errors as $key => $value) {
if (is_int($key)) {
PHPUnit::assertArrayHasKey(
$value,
$jsonErrors,
"Failed to find a validation error in the response for key: '{$value}'".PHP_EOL.PHP_EOL.$errorMessage
);
} else {
PHPUnit::assertArraySubset(
Copy link
Member

@driesvints driesvints Feb 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not introduce a new usage of assertArraySubset in Laravel. This is deprecated in PHPUnit 8 and we should avoid adding more uses of it.

Copy link
Contributor Author

@ahinkle ahinkle Feb 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@driesvints Thanks. I just read the the deprecation post(sebastianbergmann/phpunit#3494) and it's said there is no alternative.

hmm, unfortunately, now there isn't a clean way to check if a key and value matches within an array in PHPUnit and changes to use PHP here would be ugly by checking if key is set in jsonErrors then if the error message matches. Might have to table this until PHPUnit's issue/what you decide for assertJson is sorted out. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can't find an alternative we're going to backport it into the framework directly but until we figure it out it's best to avoid adding more uses.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@driesvints if you are looking for a quick way out, I ported them to a phpunit extension https://packagist.org/packages/dms/phpunit-arraysubset-asserts

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rdohms ah thanks. I'll put this on my todo list. Thanks for sharing 👍

[$key => $value],
$jsonErrors,
false,
'Failed to find a validation error in the response for key and message:'
);
}
}

return $this;
Expand Down
88 changes: 88 additions & 0 deletions tests/Foundation/FoundationTestResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,94 @@ public function testAssertJsonValidationErrorsFailsWhenGivenAnEmptyArray()
$testResponse->assertJsonValidationErrors([]);
}

public function testAssertJsonValidationErrorsWithArray()
{
$data = [
'status' => 'ok',
'errors' => ['foo' => 'one', 'bar' => 'two'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['foo', 'bar']);
}

public function testAssertJsonValidationErrorMessages()
{
$data = [
'status' => 'ok',
'errors' => ['key' => 'foo'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['key' => 'foo']);
}

public function testAssertJsonValidationErrorMessagesCanFail()
{
$this->expectException(AssertionFailedError::class);

$data = [
'status' => 'ok',
'errors' => ['key' => 'foo'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['key' => 'bar']);
}

public function testAssertJsonValidationErrorMessagesMultipleMessages()
{
$data = [
'status' => 'ok',
'errors' => ['one' => 'foo', 'two' => 'bar'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['one' => 'foo', 'two' => 'bar']);
}

public function testAssertJsonValidationErrorMessagesMixed()
{
$data = [
'status' => 'ok',
'errors' => ['one' => 'foo', 'two' => 'bar'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['one' => 'foo', 'two']);
}

public function testAssertJsonValidationErrorMessagesMixedCanFail()
{
$this->expectException(AssertionFailedError::class);

$data = [
'status' => 'ok',
'errors' => ['one' => 'foo', 'two' => 'bar'],
];

$testResponse = TestResponse::fromBaseResponse(
(new Response)->setContent(json_encode($data))
);

$testResponse->assertJsonValidationErrors(['one' => 'taylor', 'otwell']);
}

public function testAssertJsonMissingValidationErrors()
{
$baseResponse = tap(new Response, function ($response) {
Expand Down