Livewire v4 adds `assertOnlyHasErrors` for strict validation testing
Contributed by gdebrauwer
Part of the livewire v4.4.7 release
Livewire v4 ships with a new testing assertion, assertOnlyHasErrors, added in PR #10393. The method gives you a one-line way to assert that a specific set of validation errors is present and that no other validation errors exist on the component. It's a purely additive addition to the testing toolkit, so if you're upgrading from v3.8.10, nothing about your existing tests changes — but you finally get a clean way to express "this field failed, and nothing else did."
The gap in the current assertions
Before this PR, testing validation precisely required a two-step dance. assertHasErrors confirms that certain keys have errors, and assertHasNoErrors confirms that certain other keys don't. The problem is what's missing in between: any key you don't mention is ignored entirely.
// Will fail if the 'email' error is missing OR if a 'name' error is present
// BUT nothing will fail if a 'phone' error is present
$component
->assertHasErrors(['email'])
->assertHasNoErrors(['name']);
If your component validates five fields and a regression causes a sixth, unexpected field to fail, this test still passes. The only way to close that hole was to pass every possible error key to assertHasNoErrors — tedious, error-prone, and it breaks every time you add a field.
Introducing assertOnlyHasErrors
The new method collapses that pattern into a single, strict assertion:
// Will fail if the 'email' error is missing, OR if a 'name' error is
// present, OR if any other error is present
$component->assertOnlyHasErrors(['email']);
A realistic test now reads like this:
/** @test */
public function the_email_field_must_be_valid()
{
Livewire::test(ContactForm::class)
->set('email', 'not-an-email')
->call('save')
->assertOnlyHasErrors(['email']);
}
If a future change to the component also leaves name in an invalid state, the assertion fails and tells you exactly which keys were unexpected:
Component has unexpected errors: name, phone
Rule-level assertions still work
assertOnlyHasErrors supports the same two array shapes as assertHasErrors. A flat list checks that errors exist on those keys, while a keyed list additionally asserts which rule failed:
// 'email' must have a 'required' error, 'name' a 'max' error, nothing else
$component->assertOnlyHasErrors([
'email' => 'required',
'name' => 'max',
]);
Under the hood, the method first delegates to assertHasErrors($keys), so all existing behavior for rule-specific assertions is preserved. It then normalizes your key list (flattening ['email' => 'required'] down to ['email']), removes those keys from the component's actual error bag with Arr::except, and fails if anything remains.
Consistent with Laravel's own assertions
If this feels familiar, it should. The method mirrors assertOnlyJsonValidationErrors, which the same contributor previously added to Laravel's framework test assertions. Teams that already use that assertion in HTTP tests will find the semantics identical: the keys you list are the complete set of errors, not just a subset. That consistency makes it easier to reason about validation tests across your Livewire components and plain Laravel test cases.
Upgrade impact from v3.8.10
There is essentially nothing you must do:
- New method, new code path.
assertOnlyHasErrorsis additive.assertHasErrorsandassertHasNoErrorsbehave exactly as before, so no existing test can break. - Version note. The method lands in Livewire v4; it does not exist in 3.x, so tests using it won't run against v3.8.10. Fold this into your v4 migration rather than expecting it on the current release.
- No deprecations. Nothing is renamed or marked deprecated.
- Optional cleanup. Long
assertHasNoErrors([...])calls that enumerated every field can now be replaced by a singleassertOnlyHasErrors([...])call — often catching bugs those tests previously missed.
Takeaways
- Livewire v4 adds
assertOnlyHasErrors($keys)for strict validation error testing. - It fails when a listed error is missing or when any unlisted error is present.
- Both flat (
['email']) and keyed (['email' => 'required']) array syntax are supported. - It mirrors Laravel's
assertOnlyJsonValidationErrorsfor cross-framework consistency. - Upgrading from v3.8.10 requires no changes; the method is exclusive to v4.