Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Livewire Dusk Testbench Laravel Package

joshhanley/livewire-dusk-testbench

A Laravel package that brings Livewire Dusk browser testing to Orchestra Testbench, letting package developers write end-to-end Dusk tests for Livewire components without a full application skeleton. Fits neatly into existing Testbench workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

joshhanley/livewire-dusk-testbench is glue for package developers: it lets you run real browser (Dusk) tests against Livewire components using Orchestra Testbench, so you get a booted Laravel skeleton with Livewire wired up — no host application required. This is not something you install into a normal Laravel app (there you'd just use laravel/dusk + Livewire's own testing helpers).

Minimal setup for a package:

composer require --dev \
  joshhanley/livewire-dusk-testbench:"3.0.0-beta.9" \
  orchestra/testbench-dusk:^11.0 \
  livewire/livewire:^4.0

Then:

  1. Look first at the package's own tests/ directory and README. Everything you need to copy — the base TestCase, the phpunit.dusk.xml config, and the test layout view that includes @livewireScripts — lives there. Don't hand-roll a bootstrapper.
  2. Extend the shipped base test case (it registers Livewire's service provider and the route used to serve components under test). Your tests/Browser/*.php classes should extend that, not Orchestra\Testbench\Dusk\TestCase directly.
  3. Add a phpunit.dusk.xml that points at your tests/Browser suite and excludes it from your normal PHPUnit/Pest run — otherwise your unit suite will try to boot a browser.
  4. Run it: vendor/bin/dusk (or ./vendor/bin/testbench dusk) from the package root. You need Chrome/Chromium plus a matching chromedriver on the machine or in the CI image.

First use case worth writing: assert a component mounts and reacts to input.

public function test_counter_increments(): void
{
    $this->browse(function (Browser $browser) {
        $browser->visit(/* component or test route from the package */)
            ->assertSee('0')
            ->click('@increment')
            ->waitForText('1')
            ->assertSee('1');
    });
}

Implementation Patterns

One browser test per user-visible behaviour. Dusk tests are 10–100× slower than unit tests. Keep the fast Livewire Livewire::test() assertions in your normal suite and reserve Dusk for the things only a browser proves: JS hooks, Alpine interop, wire:model debounce, file uploads, wire:navigate, third-party JS.

Fixture components live in your package's test namespace. Register them with the package's provider (or a small test-only service provider) so they're resolvable from the Dusk route. Keep them tiny — a Dusk fixture that mirrors your real component will drift.

Use Testbench's workbench for views and layouts. Put the test layout in workbench/resources/views/ (or wherever your testbench version expects it) and make sure @livewireScripts and @livewireStyles are present. A missing @livewireScripts produces a page that renders perfectly and never responds to clicks — the single most common "Livewire is broken" symptom here.

Version matrix in CI, with the beta job separated. Because this release targets Livewire 4 / testbench-dusk 11 (Laravel 13), run it as its own job:

jobs:
  dusk-stable:      # livewire ^3, testbench-dusk ^10
  dusk-livewire-4:  # livewire ^4, testbench-dusk ^11, this beta
    continue-on-error: true

Mark the beta job non-blocking until 3.0.0 goes stable, so an upstream Livewire 4 beta regression doesn't red your default branch.

Debugging loop: vendor/bin/dusk --browse to watch it, --filter to isolate one test, and $browser->dump() / ->screenshot('name') mid-flow. Console errors from Livewire surface in $browser->driver->manage()->getLog('browser') — worth a helper that dumps them on failure, because a thrown JS error in Livewire 4 looks identical to "the click did nothing."

Cleanup pattern: use DatabaseMigrations (not RefreshDatabase) — Dusk runs in a separate process from the test runner, so transaction rollback won't apply the way you expect.

Gotchas and Tips

  • It's a beta, and it's pinned to a beta ecosystem. 3.0.0-beta.9 implies testbench-dusk ^11 (Laravel 13) and Livewire 4. If you're on Laravel 11/12 + Livewire 3, stay on the 2.x line — mixing will fail in confusing ways (service provider ordering, missing JS globals, route 404s). Pin the exact beta version in composer.json; ^3.0@beta will silently move you to a different beta with different upstream constraints.
  • 404s mean wiring, not routing. If visit() 404s, the package's service provider isn't registered in your base test case, or your component isn't registered with it. Check that first before digging into Dusk.
  • Chromedriver/Chrome version mismatch is the #1 flake, and it surfaces as timeouts that look like Livewire timing bugs. Pin both in CI (setup-chrome + matching driver) rather than relying on whatever's preinstalled.
  • Timing: prefer waitFor* over bare assertSee. Livewire 4's DOM morphing means the element can exist with stale text; waitForText, waitUntilMissing, waitFor('@selector') are your friends. Bare assertSee after a click is a flaky test waiting to happen.
  • State leaks between tests. A Dusk browser session persists across browse() calls in the same test. Log out / clear cookies / reset localStorage explicitly if you test auth or persisted state.
  • Don't run Dusk in the same job as your unit suite — it needs a display (use xvfb-run on Linux) and roughly 100× the wall clock.
  • Extension points: the package is deliberately thin. When you need custom behaviour (extra providers, custom test routes, a component registry), add your own TestCase subclass on top of theirs rather than forking. Publishable config/routes, if present, are the intended seam — check vendor/joshhanley/livewire-dusk-testbench/ after install before writing a workaround.
  • Watch the changelog for beta-to-stable. The two things that will force work on your side are (a) Livewire 4 JS asset changes breaking your test layout, and (b) testbench-dusk 11 changing the workbench directory layout. Both land in your test scaffolding, not your runtime code — so the blast radius stays inside tests/.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource