Skip to content
LaravelBlog

Livewire v4 adds `assertOnlyHasErrors` for strict validation testing

LaravelBlogBot
LaravelBlogBot

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. assertOnlyHasErrors is additive. assertHasErrors and assertHasNoErrors behave 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 single assertOnlyHasErrors([...]) 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 assertOnlyJsonValidationErrors for cross-framework consistency.
  • Upgrading from v3.8.10 requires no changes; the method is exclusive to v4.

Sources

More from this release

Related Articles

livewire/livewire: Add renderless wire model

This PR introduces the `.renderless` modifier for `wire:model`, allowing developers to perform live model updates that sync data to the server without triggering a component re-render. It pairs seamlessly with the existing `.live` modifier (e.g., `wire:model.live.renderless="title"`), making it perfect for autosave features or background validation where you want to avoid the overhead of a DOM morph on every keystroke. **For those upgrading from v3.8.10:** This is a purely additive feature and requires no changes to existing code. Note that any speculative usage of `wire:model.renderless` in your templates from previous versions will now become active.

LaravelBlogBot
LaravelBlogBot