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

[9.x] Add new assertJsonValidationErrorRule testing helper #41239

Closed

Conversation

danilopolani
Copy link
Contributor

This PR proposes and adds a new assertJsonValidationErrorRule testing helper for HTTP testing.
If approved and merged I'll submit a PR for the docs too in the new 2 days 🤞

Why

Currently if you want to test that your endpoint returns a validation error you can use assertJsonValidationErrorFor or assertJsonValidationErrors. The issue with both of them is that you're probably just checking that a validation error is returned, but not what error is returned; this is not the best idea because your test could fail for another reason.

If you want to check for a specific error you have to compile the message error yourself (replacing the placeholders) or just harcoding it.

$this->postJson('/')
    ->assertJsonValidationErrorFor('foo'); // This passes, but what's the error message? It can be everything

$this->postJson('/')
    ->assertJsonValidationErrors([
        'foo' => 'The foo field is required.', // Hardcoded
    ]);

$this->postJson('/')
    ->assertJsonValidationErrors([
        'foo' => str_replace(':attribute', 'foo', trans('validation.required')), // Manual replacing, how do you handle custom rules? And what about rule arguments?
    ]);

Solution

The new assertJsonValidationErrorRule, in conjuction with a new Validator public method to compile messages, can take care of everything for you: it retrieves the translated message, does the replaces and works with custom rules too.

$this->postJson('/')
    ->assertJsonValidationErrorRule('foo', 'required'); // Compiles to "The foo field is required."

You can search for multiple errors too:

$this->postJson('/')
    ->assertJsonValidationErrorRule([
        'foo' => 'required', // Compiles to "The foo field is required."
        'bar' => 'required_array_keys:foo,baz', // Compiles to "The bar field must contain entries for foo, baz"
    ]);

And, of course, you can pass your custom validation rule:

class MyCustomRule implements Rule
{
    public function passes($attribute, $value)
    {
        return $value === 'baz';
    }

    public function message()
    {
        return ':attribute must be baz';
    }
}

$this->postJson('/')
    ->assertJsonValidationErrorRule('foo', new MyCustomRule()); // Compiles to "foo must be baz"

@danilopolani danilopolani changed the title Add new assertJsonValidationErrorRule testing helper [9.x] Add new assertJsonValidationErrorRule testing helper Feb 24, 2022
@taylorotwell
Copy link
Member

I would just do $response->assertInvalid(['foo' => 'required']); - you do not need to provide the full error message... just a substring.

@danilopolani
Copy link
Contributor Author

danilopolani commented Feb 25, 2022

@taylorotwell I got it, but IMHO that's not 100% accurate: for example similar error messages require more and more precision, if you change the validation message (it applies a lot for custom rules) you have to manually replace all the errors in your tests (and you can't use trans because of the placeholders) and having the validation rule is definitely easier to match with your business logic, also because you would not need to remember/read the error manually and write it in your test.

With this functionality you have a "single point of truth" that - at least to me - it makes everything quicker, centralized and less manual.
Would love to hear your thoughts too 😄


Since this seems to a dead end, I've made a package to achieve the same result: https://github.com/danilopolani/laravel-json-validation-testing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants