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

Laravel Dusk Fakes Laravel Package

protonemedia/laravel-dusk-fakes

Laravel Dusk Fakes lets you replace real Dusk browser sessions with fakes in your tests. It offers a fluent API to simulate browser interactions and assert Dusk calls, so you can test Dusk-dependent code quickly without launching a real browser.

View on GitHub
Deep Wiki
Context7

Getting Started

Add the package as a dev dependency and publish its config:

composer require protonemedia/laravel-dusk-fakes --dev
php artisan vendor:publish --tag=dusk-fakes-config

The package bridges a fundamental Dusk problem: your PHPUnit process and the application under test are two different processes, so a plain Mail::fake() in setUp() never reaches the app the browser is driving. This package persists fake registrations and recorded interactions to a shared store (typically under storage/framework/) so both sides see the same state.

Where to look first, in order:

  1. config/dusk-fakes.php — enable flag, storage path, and which fakes are supported.
  2. The DuskFakes trait (or facade, depending on version) in vendor/protonemedia/laravel-dusk-fakes/src — this is the real API surface: the fake* toggles and assert* helpers.
  3. Your base DuskTestCase — this is where the trait belongs so every browser test can opt in.

A first use case that pays for itself immediately: a registration flow where the controller sends a welcome email and dispatches a job. Fake Mail and Queue at the top of the test, drive the browser through the form, then assert the mail was "sent" to the right address and the job was queued — with no SMTP server and no queue worker involved:

use ProtoneMedia\LaravelDuskFakes\DuskFakes;

class RegistrationTest extends DuskTestCase
{
    use DuskFakes;

    public function test_new_user_is_welcomed()
    {
        $this->fakeMail();
        $this->fakeQueue();

        $this->browse(function (Browser $browser) {
            $browser->visit('/register')
                ->type('email', '[email protected]')
                ->press('Register')
                ->assertPathIs('/dashboard');
        });

        $this->assertMailSent(fn ($mail) => $mail->hasTo('[email protected]'));
        $this->assertQueued(SendWelcomeSequence::class);
    }
}

Implementation Patterns

Default to faking, opt out per test. Put the common fakes in DuskTestCase::setUp() (Mail, Notifications, HTTP) and only add Queue/Event/Bus fakes in tests that care. This keeps every browser test hermetic by default — no accidental emails from CI, no calls to Stripe or a mailing list.

Use HTTP fakes to make third-party flows deterministic. If a page calls an external API (payment provider, address lookup, feature flag service), fake the HTTP client and return a fixture. The same fake lets you assert the request payload the browser-driven app produced. This is the single biggest reliability win for Dusk suites.

Mirror Laravel's own fake assertions. The package intentionally exposes the same shape (assertSent, assertNothingSent, assertQueued, assertDispatched, and so on) so muscle memory from feature tests carries over. When porting an existing feature test into a Dusk test, the assertion block usually survives with a one-line change to the fake setup.

Combine with browser macros. Register a fakeCheckout() macro on Browser that wires the fakes and stubs the expected HTTP responses, then call it from every checkout test. This keeps per-test setup to a single line and centralizes fixture payloads.

Reset between tests. Call the package's reset/clear method in tearDown() (or re-fake in setUp()). Recorded calls accumulate in the shared store; without cleanup you'll get false positives from a previous test's mail or queued job.

Negative tests are cheap. assertNothingSent() after a failed validation flow is a fast, high-value test that catches accidental mail sends on error paths — a class of bug that plain feature tests often miss because the controller returns before the fake is inspected.

Keep the package out of non-test environments. The service provider swaps container bindings, so guard it with APP_ENV=testing (or the package's enabled config bound to an env var). Never let this ship to staging or production.

Gotchas and Tips

  • Two-process storage is the whole trick — and the whole failure mode. The store path must be writable by the process serving the app and readable by the PHPUnit process. On Docker/CI, confirm the same volume is mounted for both; silent assertion failures are usually a permissions or path problem, not an API problem.
  • Parallel Dusk runs collide. If you use dusk --parallel, separate processes may write to the same state file. Either run fakes-using tests serially or verify the installed version namespaces its state per test. Check this before scaling your suite.
  • Timing matters. Fakes must be registered before the browser triggers the action. Registering a fake after a click that already fired the mail won't retroactively capture it.
  • Queue fake vs. real worker. Faking the queue only records dispatch — it doesn't prove the job runs. If the job's side effect (sending a notification, updating a record) is what you actually care about, test that separately with QUEUE_CONNECTION=sync, or assert the browser reflects the eventual state.
  • Small package, small API. With ~21 stars and essentially no dependents, method names and config keys have shifted across releases. Pin the version in composer.json and read the trait source in vendor/ rather than relying on blog posts — the source is short and is the most accurate documentation you'll get.
  • Debugging tip: open the JSON state file directly after a failing test. Seeing the recorded payload is usually faster than adding dd() calls in a controller running in a separate process.
  • Extension point: if you need to fake something the package doesn't cover, the same persistence mechanism can wrap your own interface — bind a fake implementation in a service provider keyed off the package's config flag, and record calls to the same store.
  • Don't use it as a substitute for feature tests. Dusk is slow. Reserve these fakes for flows that genuinely need a browser (JS, cookies, multi-step UI); plain HTTP feature tests with Laravel's native fakes remain the right tool for everything else.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib