Summer Sale! All accounts are 50% off this week.

luddinus's avatar

What happened with "assertInvalid" rule?

Hello,

I remember reading a Taylor Otwell tweet that explains a new feature (last year more or less) to assertInvalid data like this:

	$this->assertInvalid(['body' => ['required']]);

https://freek.dev/2096-asserting-valid-and-invalid-requests-in-laravel

Today works but the values passed to the array is the message, not the rule against you want to check.

It was like the "assertHasErrors" of Livewire's.

https://laravel-livewire.com/docs/2.x/input-validation#testing-validation

I'm looking the Laravel framework commits but not lucky at this moment.

0 likes
7 replies
luddinus's avatar

@Nakov Sorry, the example was bad, I'm using on the response.

Array from string conversion is the error. In this particularly case will work because it search the string "required" in the error message

$response->assertInvalid(['body' => 'required']);

But it does not asserts that the Required Rule exist...

Nakov's avatar

@luddinus if this is the error Array from string conversion is the error. that does not mean that the assertInvalid does not work, but something else is going on. Each error has the number line, so check why and where does the error shows and make sure you fix that code.

luddinus's avatar

@Nakov Forget about the error. This is what I mean:

class PostsController
{
   public function store()
   {
      request()->validate([
         'body' => ['required', 'min:10'],
         // ...
      ]);
   }
}

some test

$response = $this->post('api/posts', []);
$response->assertInvalid(['title' => 'required']);

This will pass because the $errors->title contains the "required" string, but the "assertInvalid" doest not assert that there is a Validator with the "required" rule failed.

other test

$response = $this->post('api/posts', ['title' => 'short']);
$response->assertInvalid(['title' => 'min']);

This fails because the message is something like "The title must be at least 10 characters", and doest not check that there is a Validator with the "min" rule failed. THAT'S the feature I expect. Not the error message.

martinbean's avatar
Level 80

@luddinus The array value is a string to check for in the validation failure message; not a rule name. If the validation message does not contain the string “min” then it will not be considered invalid. This is mentioned in the documentation for the method:

https://laravel.com/docs/9.x/http-tests#assert-invalid

You may also assert that a given key has a particular validation error message. When doing so, you may provide the entire message or only a small portion of the message

1 like
Nakov's avatar

@luddinus Okay I see what you are saying. The thing is that the value for the key in the assertion is not really the rule, but it has to be something from the error message. So in your case this will be the correct way:

$response->assertInvalid(['body' => 'required']); // the error message contains required

$response = $this->post('/test', ['body' => 'short']);

$response->assertInvalid(['body' => 'characters']); // the error message contains characters

P.S. I had it opened on this page while testing, and just now see that @martinbean has already left a good comment pointing to the documentation. So that's it with examples above :)

1 like
luddinus's avatar

@martinbean @nakov

My mistake.

Looking the commit @nakov mentioned, I thought there was a time that the "assertInvalid" behaviour was what I want (check that a specific rule fails). I thought that the "required" parameter passed was the rule, not that the message contains "required" string :(

I'm looking Livewire's source code and maybe I'm going to make a pull request to Laravel's core.

Thanks.

Please or to participate in this conversation.