I'll prefix this with not being able to take credit with the solution, but the tl;dr is to read the docs!.
I've been upgrading this app from Livewire 2.x days through to now, and as I've been introducing new functionality to it and running the full test suite often as I do, it all ran really fast until a handful of tests right near the end that made the suite appear to just... hang.
I first ran Pest's profile tool pest --profile to find which tests were getting stuck to find two in particular, both of them testing Livewire components.
Looking at the code, it seemed fairly inoccuous:
// Truncated for brevity
it('can apply to speak', function () {
$event = Event::factory()->create();
livewire(ApplyToSpeak::class)
->fill(validSubmission())
->call('save')
->assertDispatched('toast-show')
->assertRedirectToRoute('apply-to-speak');
assertDatabaseHas(User::class, [...])
});
Now I mentioned that I had upgraded this from a 2.x app, so must have missed this along the way and you might have spotted it already, but the fix was simple (thanks, Amp for finding it).
// Truncated for brevity
it('can apply to speak', function () {
$event = Event::factory()->create();
livewire(ApplyToSpeak::class)
->fill(validSubmission())
->set('form', validSubmission())
->call('save')
->assertDispatched('toast-show')
->assertRedirectToRoute('apply-to-speak');
assertDatabaseHas(User::class, [...])
});
Small change, big impact; changing fill to set reduced the full test suite from ~22sec - with many tests in the 0.9s - 1.3s range - down to ~4sec, where the slowest test is now 290ms.
Looking at the docs, you won't even find the fill method mentioned at all.
The subtle difference between the two methods is that fill triggers one Livewire round-trip per field, while using set will only trigger one.
Written by Michael Dyrynda
Principal Engineer, Laravel enthusiast, and open source contributor. I write about web development, PHP, and the problems I solve along the way.