Skip to main content

Command Palette

Search for a command to run...

Laravel Dusk: Simplifying Browser Testing for Web Developers

Updated
5 min read
Laravel Dusk: Simplifying Browser Testing for Web Developers

Browser Testing for Laravel Developers

Introduction

Imagine you're building a complex web application and want to ensure everything works perfectly from a user's perspective. Enter Laravel Dusk – your friendly neighborhood browser testing companion! 🕵️‍♀️🌐

Laravel Dusk is an elegant browser automation and testing tool that allows you to write and run end-to-end tests for your web applications as if a real user were interacting with your site. No more manual clicking and checking – Dusk does the heavy lifting for you!

Browser

What is Laravel Dusk?

Laravel Dusk provides a simple, expressive API for automating and testing your web applications in a real browser environment. Unlike traditional unit or feature tests that check individual components, Dusk tests the entire user experience from start to finish.

Key Features

  • Real browser testing

  • No JavaScript configuration required

  • Chrome and Firefox support

  • Easy element selection

  • Automatic screenshot capture on test failure

  • Interaction simulation (clicking, typing, scrolling)

Setting Up Laravel Dusk

Let's walk through a step-by-step setup process:

1. Install Laravel Project

composer create-project --prefer-dist laravel/laravel dusk-demo
cd dusk-demo

2. Install Laravel Dusk

composer require --dev laravel/dusk
php artisan dusk:install

3. Configure ChromeDriver

php artisan dusk:chrome-driver

Real-World Testing Scenarios

Let's explore some relatable testing scenarios that demonstrate Dusk's capabilities:

Scenario 1: User Registration

Imagine you're building a recipe sharing platform. You want to ensure users can successfully register.

<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class RegistrationTest extends DuskTestCase
{
    use DatabaseMigrations;

    public function testSuccessfulRegistration()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/register')
                   ->type('name', 'Jamie Oliver')
                   ->type('email', 'jamie@example.com')
                   ->type('password', 'SecureChef123!')
                   ->type('password_confirmation', 'SecureChef123!')
                   ->press('Register')
                   ->assertPathIs('/dashboard')
                   ->assertSee('Welcome, Jamie!');
        });
    }
}

Scenario 2: Online Shopping Checkout

Consider an e-commerce site where you want to test the complete checkout process:

public function testCompleteCheckoutProcess()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/products')
               ->clickLink('Add to Cart')
               ->assertSee('1 item in cart')
               ->click('@proceed-to-checkout')
               ->type('@card-number', '4111111111111111')
               ->type('@expiry-date', '12/25')
               ->type('@cvv', '123')
               ->press('Complete Purchase')
               ->waitForText('Order Confirmed')
               ->assertPathIs('/order/confirmation');
    });
}

Advanced Dusk Techniques

Handling JavaScript-Heavy Interactions

Dusk shines when dealing with dynamic content:

public function testAutocompleteFunctionality()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/search')
               ->type('#search-input', 'Laravel')
               ->waitForText('Laravel Dusk')
               ->clickLink('Laravel Dusk')
               ->assertPathIs('/docs/dusk');
    });
}

Responsive Design Testing

Test how your site looks across different screen sizes:

public function testResponsiveNavigation()
{
    $this->browse(function (Browser $browser) {
        $browser->resize(375, 812)  // iPhone X size
               ->visit('/')
               ->assertVisible('@mobile-menu-toggle')
               ->click('@mobile-menu-toggle')
               ->assertSee('Mobile Navigation Menu');
    });
}

Authenticated User Testing

Testing scenarios for authenticated users is crucial for many web applications. Laravel Dusk makes it incredibly simple to simulate logged-in user interactions. Let's explore a comprehensive example that demonstrates authentication and subsequent actions.

Creating an Authenticated User Test

<?php

namespace Tests\Browser;

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class AuthenticatedUserTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A detailed test for an authenticated user's profile management
     */
    public function testUserProfileManagement()
    {
        // Create a test user
        $user = User::factory()->create([
            'name' => 'John Doe',
            'email' => 'john@example.com',
            'password' => bcrypt('password123')
        ]);

        $this->browse(function (Browser $browser) use ($user) {
            $browser
                // Navigate to login page
                ->visit('/login')

                // Perform login
                ->type('email', $user->email)
                ->type('password', 'password123')
                ->press('Login')

                // Assert successful login
                ->assertAuthenticated()
                ->assertPathIs('/dashboard')

                // Navigate to profile page
                ->clickLink('Profile Settings')
                ->assertPathIs('/profile')

                // Update profile information
                ->type('@name-input', 'John Smith')
                ->type('@bio-input', 'Software Engineer | Laravel Enthusiast')

                // Upload profile picture (simulating file upload)
                ->attach('@profile-picture', storage_path('test-avatar.jpg'))

                // Save profile changes
                ->press('Update Profile')

                // Assert success message and updated information
                ->waitForText('Profile Updated Successfully')
                ->assertSee('John Smith')
                ->assertSee('Software Engineer | Laravel Enthusiast')

                // Optional: Check notification or toast message
                ->assertVisible('@success-notification');
        });
    }

    /**
     * Test secure areas and authorization
     */
    public function testUnauthorizedAccessRestriction()
    {
        $user = User::factory()->create();
        $adminUser = User::factory()->create(['is_admin' => true]);

        $this->browse(function (Browser $browser) use ($user, $adminUser) {
            // Test regular user cannot access admin panel
            $browser->loginAs($user)
                    ->visit('/admin/dashboard')
                    ->assertPathIs('/dashboard')
                    ->assertSee('Unauthorized Access');

            // Test admin user can access admin panel
            $browser->loginAs($adminUser)
                    ->visit('/admin/dashboard')
                    ->assertPathIs('/admin/dashboard')
                    ->assertSee('Admin Control Panel');
        });
    }

    /**
     * Simulate a complex workflow like creating a project
     */
    public function testProjectCreationWorkflow()
    {
        $user = User::factory()->create();

        $this->browse(function (Browser $browser) use ($user) {
            $browser->loginAs($user)
                    ->visit('/projects')
                    ->clickLink('Create New Project')

                    // Fill out project details
                    ->type('@project-name', 'Laravel Dusk Testing Guide')
                    ->type('@project-description', 'A comprehensive guide to browser testing')

                    // Select project type
                    ->select('@project-type', 'documentation')

                    // Invite team members
                    ->type('@team-member-email', 'colleague@example.com')
                    ->press('Add Team Member')

                    // Submit project
                    ->press('Create Project')

                    // Assertions
                    ->waitForText('Project Created Successfully')
                    ->assertSee('Laravel Dusk Testing Guide')
                    ->assertPathBeginsWith('/projects/');
        });
    }
}

Breaking Down the Authenticated User Tests

1. User Profile Management Test

  • Demonstrates logging in with a created user

  • Shows how to interact with form elements

  • Simulates file upload

  • Checks for successful profile updates

2. Authorization Test

  • Verifies different user roles

  • Checks access restrictions

  • Demonstrates login with specific user types

3. Complex Workflow Test

  • Simulates a multi-step project creation process

  • Shows interaction with dropdowns, text inputs

  • Demonstrates team collaboration features

Key Authentication Testing Strategies

  1. User Factory: Use Laravel's model factories to create test users

  2. Login Methods:

    • Manual login via form

    • loginAs() method for quick authentication

  3. Role-Based Testing: Verify different user permissions

  4. Workflow Simulation: Test complete user journeys

Best Practices

  1. Keep tests focused and specific

  2. Use meaningful assertion messages

  3. Leverage Dusk's built-in waiting mechanisms

  4. Organize tests logically

  5. Use environment-specific configurations

Running Your Tests

# Run all Dusk tests
php artisan dusk

# Run a specific test
php artisan dusk tests/Browser/RegistrationTest.php

Additional Authentication Testing Tips

  • Always reset the database between tests

  • Use different user roles and scenarios

  • Cover both positive and negative authentication flows

  • Test edge cases like password reset, email verification

  • Login with valid/invalid credentials

  • Password reset process

  • Email verification

  • Multi-factor authentication

  • Session management

  • Logout functionality

Conclusion

Laravel Dusk transforms browser testing from a tedious chore into an enjoyable, efficient process. By simulating real user interactions, you can catch issues before they reach production and ensure a smooth user experience.

Quick Tips

  • Start with simple scenarios

  • Gradually increase test complexity

  • Integrate Dusk into your CI/CD pipeline

  • Keep your test suite lean and meaningful

Happy testing, Laravel developers! 🚀👩‍💻👨‍💻

Pro Tip: Combine Dusk with continuous integration tools like GitHub Actions or GitLab CI to automatically run tests on every code push.

More from this blog

Sohag's Notes

79 posts

Tech Lead at MobyPay | Certified Laravel Developer | PHP JS GO | DevOps Enthusiast | Open to projects