Laravel Dusk: Simplifying Browser Testing for Web Developers

Sohag HasanSohag Hasan
5 min read

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.

0
Subscribe to my newsletter

Read articles from Sohag Hasan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sohag Hasan
Sohag Hasan

WhoAmI => notes.sohag.pro/author