Great question! Let’s clarify how Livewire’s #[Validate] attribute and the $this->validate() method interact, and how you can test for their necessity.
1. What does #[Validate] do?
When you use the #[Validate] attribute on a property, Livewire will automatically validate that property when it is updated (e.g., when the user types in an input bound to that property). This is called "field-level validation" or "on update validation".
However:
This automatic validation only runs for properties that are being updated. If a property is never updated by the user (e.g., a hidden field, or one not present in the form), its validation rule is not enforced unless you call $this->validate() manually.
2. What does $this->validate() do?
Calling $this->validate() in your action method (like submit()) will validate all properties with validation rules, regardless of whether they were updated or not. This is essential before you perform critical actions like authentication or saving to the database.
3. Should you call $this->validate() in submit()?
Yes, you should!
Even with #[Validate] attributes, you should call $this->validate() in your submit() method to ensure all validation rules are enforced at the time of submission, not just those that were updated.
4. Why do your tests still pass if you remove $this->validate()?
Your current tests only check for validation errors when you set the property and call submit(). Since Livewire validates on update, the errors are triggered as expected.
However, if you want to ensure that $this->validate() is necessary, you need to test the scenario where a property is never updated, but still required.
5. How can you write a test that fails if $this->validate() is removed?
Write a test where you do not set one of the required properties before calling submit(). For example, don’t set the password property:
it('requires a password even if not updated', function () {
Livewire::test(SignIn::class)
->set('email', '[email protected]')
->call('submit')
->assertHasErrors(['password' => 'required']);
});
If you remove $this->validate() from submit(), this test will fail (i.e., it will not catch the missing password), because Livewire only validates properties on update unless you call $this->validate().
Summary
- Always call
$this->validate()in your submit methods to ensure all rules are enforced. - The
#[Validate]attribute only validates on property update. - To test the necessity of
$this->validate(), write a test where you do not set all required properties before submission.
References:
Let me know if you’d like more examples or clarification!