christophrumpel/missing-livewire-assertions
Installation:
composer require --dev christophrumpel/missing-livewire-assertions
Add the service provider to config/app.php under providers:
ChristophRumpel\MissingLivewireAssertions\MissingLivewireAssertionsServiceProvider::class,
First Use Case: Test a Livewire component's emitted events:
use function ChristophRumpel\MissingLivewireAssertions\assertEmitted;
$this->livewire(YourComponent::class)
->assertEmitted('event-name'); // Checks if the event was emitted
assertEmitted, assertNotEmitted, assertHasErrors, assertHasNoErrors, etc.).Testing Event Emissions:
$this->livewire(YourComponent::class)
->call('triggerEvent')
->assertEmitted('custom-event')
->assertEmitted('custom-event', ['param1', 'param2']); // With payload
Validating Form State:
$this->livewire(YourFormComponent::class)
->fill('email', 'invalid-email')
->press('submit')
->assertHasErrors(['email' => 'required|email']);
Asserting UI State:
$this->livewire(YourComponent::class)
->assertSee('Expected Text')
->assertDontSee('Unexpected Text')
->assertDisabled('submit-button');
Testing Component Interactions:
$this->livewire(ParentComponent::class)
->assertChildComponent(ChildComponent::class)
->assertChildComponentCount(ChildComponent::class, 2);
Mocking External Dependencies: Use assertions to verify interactions with external services (e.g., API calls) via emitted events or error states.
Combine with Laravel Test Helpers:
Pair with Laravel’s built-in assertions (e.g., assertDatabaseHas) for end-to-end testing:
$this->livewire(YourComponent::class)
->call('save')
->assertEmitted('saved')
->assertDatabaseHas('posts', ['title' => 'Test Post']);
Custom Assertions: Extend the package by creating custom assertions in your test classes:
use function ChristophRumpel\MissingLivewireAssertions\assertEmitted;
function assertCustomEventEmitted($component, $event, $payload = null) {
$component->assertEmitted($event, $payload);
// Add additional logic
}
Livewire Test Traits:
Use the package alongside Livewire\Testing\TestableLivewire for seamless integration:
use Livewire\Testing\TestableLivewire;
use ChristophRumpel\MissingLivewireAssertions\MissingLivewireAssertions;
class YourTest extends TestCase {
use TestableLivewire, MissingLivewireAssertions;
}
Testing Real-Time Updates:
Verify real-time updates (e.g., wire:model.live) by asserting emitted events or UI changes:
$this->livewire(RealTimeComponent::class)
->assertSee('Initial Value')
->call('updateValue')
->assertSee('Updated Value');
Event Scope:
dispatchBrowserEvent), ensure the test waits for them:
$this->livewire(YourComponent::class)
->call('asyncAction')
->waitForEvent('event-name'); // If using Pest
sleep() or custom assertions with timeouts (not ideal, but works for simple cases).Component Lifecycle:
assertHasErrors or assertHasNoErrors must be called after interactions (e.g., fill or press). Calling them prematurely may fail:
// ❌ Fails (errors not yet processed)
$this->livewire(YourComponent::class)
->assertHasNoErrors();
// ✅ Works
$this->livewire(YourComponent::class)
->fill('email', 'invalid')
->press('submit')
->assertHasErrors();
Child Component Assertions:
assertChildComponent requires the exact class name (including namespace). Use get_class() in your component if unsure:
$this->livewire(ParentComponent::class)
->assertChildComponent(\App\Http\Livewire\ChildComponent::class);
Flaky Tests:
refresh() to reset the component state if needed:
$this->livewire(YourComponent::class)
->call('action')
->refresh()
->assertEmitted('reset');
Log Emitted Events: Temporarily log events in your component to debug:
protected $listeners = ['event-name' => 'handleEvent'];
public function handleEvent($payload) {
\Log::info('Event received:', $payload);
}
Inspect Component State:
Use dump() or dd() in your test to inspect the component’s properties:
$this->livewire(YourComponent::class)
->call('action')
->assertEmitted('event')
->dump(); // Inspect component state
Verify Test Environment: Ensure your test environment matches production (e.g., same Livewire version). Run:
composer show livewire/livewire
And compare with your composer.json.
No Configuration Needed: The package is zero-config. Install and use assertions directly in tests.
Custom Assertion Namespaces: If you encounter naming conflicts, alias the assertions in your test class:
use function ChristophRumpel\MissingLivewireAssertions\assertEmitted as assertCustomEmitted;
Add Custom Assertions: Extend the package by publishing your own assertions. Fork the repository or create a wrapper:
// app/Testing/Assertions.php
function assertCustomAssertion($component, $condition) {
// Custom logic
assert(true, "Custom assertion passed");
}
Mock Event Dispatching:
For isolated testing, mock the dispatchBrowserEvent method in your component:
$component = $this->livewire(YourComponent::class);
$component->shouldReceive('dispatchBrowserEvent')->once();
Integration with Testing Frameworks:
expect() for fluent assertions:
expect($this->livewire(YourComponent::class))
->toHaveEmitted('event-name');
assertTrue() or custom matchers:
$this->assertTrue(
$this->livewire(YourComponent::class)->assertEmitted('event-name')
);
How can I help you explore Laravel packages today?