Weave Code
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

Browser Laravel Package

zenstruck/browser

A Laravel-friendly browser testing toolkit built on Symfony BrowserKit and Panther. Easily crawl pages, click links, submit forms, assert on HTML, and drive real headless browsers—great for end-to-end tests and fluent, expressive UI assertions.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require zenstruck/browser --dev
    

    Add the PHPUnit extension to phpunit.xml:

    <extensions>
        <extension class="Zenstruck\Browser\Test\BrowserExtension" />
    </extensions>
    
  2. Basic Test Setup: Extend your test class with HasBrowser trait and ensure it extends either:

    • Symfony\Bundle\FrameworkBundle\Test\KernelTestCase (for KernelBrowser)
    • Symfony\Component\Panther\PantherTestCase (for PantherBrowser)
    use Zenstruck\Browser\Test\HasBrowser;
    
    class MyTest extends KernelTestCase
    {
        use HasBrowser;
    
        public function testBasicPageVisit()
        {
            $this->browser()
                ->visit('/')
                ->assertSee('Welcome');
        }
    }
    

First Use Case

Test a simple form submission:

public function testFormSubmission()
{
    $this->browser()
        ->visit('/contact')
        ->fillField('name', 'John Doe')
        ->fillField('email', 'john@example.com')
        ->click('Submit')
        ->assertSee('Thank you, John Doe');
}

Implementation Patterns

Common Workflows

1. Testing User Authentication

public function testAuthenticatedAccess()
{
    $user = $this->createTestUser(); // Your user factory method

    $this->browser()
        ->actingAs($user)
        ->visit('/dashboard')
        ->assertSee('Welcome, ' . $user->getUsername());
}

2. API Testing with JSON Responses

public function testApiResponse()
{
    $this->browser()
        ->post('/api/users', HttpOptions::json(['name' => 'Alice']))
        ->assertJson()
        ->assertJsonMatches('id', 1)
        ->assertJsonMatches('name', 'Alice');
}

3. JavaScript-Dependent Tests (PantherBrowser)

public function testDynamicContent()
{
    $this->pantherBrowser()
        ->visit('/dashboard')
        ->waitFor('.user-menu') // Wait for JS-rendered element
        ->click('.user-menu')
        ->assertSee('Logout');
}

4. Form Validation Testing

public function testFormValidation()
{
    $this->browser()
        ->visit('/register')
        ->fillField('email', 'invalid-email')
        ->click('Submit')
        ->assertSee('The email must be a valid email address.');
}

5. Redirect Testing

public function testRedirectAfterLogin()
{
    $this->browser()
        ->visit('/login')
        ->fillField('email', 'user@example.com')
        ->fillField('password', 'password')
        ->click('Login')
        ->assertRedirectedTo('/dashboard');
}

Integration Tips

Combining with zenstruck/foundry

use Zenstruck\Foundry\Test\Factories;

class UserTest extends KernelTestCase
{
    use HasBrowser, Factories;

    public function testUserCreation()
    {
        $user = UserFactory::new()->create();

        $this->browser()
            ->actingAs($user)
            ->visit('/profile')
            ->assertSee($user->getEmail());
    }
}

Custom Assertions

Extend the Browser class to add domain-specific assertions:

class CustomBrowser extends Browser
{
    public function assertFlashMessage(string $message)
    {
        $this->assertSeeIn('.alert', $message);
    }
}

// Usage in test:
$this->browser()->assertFlashMessage('Success!');

Environment-Specific Config

Use environment variables to control behavior:

// .env.test
BROWSER_SOURCE_DIR=/tmp/browser_sources
BROWSER_CATCH_EXCEPTIONS=false

Debugging with dd() and dump()

public function testDebugResponse()
{
    $this->browser()
        ->visit('/complex-page')
        ->dump('body') // Dump HTML body
        ->dd('data.users[0].name'); // Dump and die for JSON response
}

Gotchas and Tips

Pitfalls

  1. Authentication Issues:

    • If you see LogicException: Cannot create the remember-me cookie, ensure:
      • You’ve visited a page that triggers security checks (e.g., a route with is_granted()).
      • Profiling is enabled (->withProfiling() or framework.profiler.collect: true in config/packages/test.php).
  2. PantherBrowser Slowness:

    • PantherBrowser spins up a real browser, making tests ~10x slower than KernelBrowser.
    • Use sparingly for critical JS-dependent flows.
  3. Redirect Handling:

    • By default, redirects are followed. Use ->interceptRedirects() to inspect redirect responses.
    • Example:
      $this->browser()
          ->visit('/login')
          ->interceptRedirects()
          ->click('Logout')
          ->assertRedirected();
      
  4. Exception Handling:

    • Exceptions are caught by default. Disable with ->throwExceptions() if you need expectException().
    • Example:
      $this->browser()
          ->throwExceptions()
          ->visit('/admin'); // Fails if unauthorized
      
  5. Kernel Rebooting:

    • The kernel is rebooted between requests by default. Disable with ->disableReboot() for performance-critical tests (e.g., API suites).
    • Re-enable with ->enableReboot() if needed.
  6. JMESPath Dependencies:

    • Requires mtdowling/jmespath.php for JSON assertions. Install with:
      composer require --dev mtdowling/jmespath.php
      

Debugging Tips

  1. Save Source for Inspection:

    $this->browser()
        ->visit('/problem-page')
        ->saveSource('debug.html'); // Saves to `var/browser/source/debug.html`
    
  2. Inspect Cookies:

    $this->browser()->use(function (CookieJar $cookieJar) {
        var_dump($cookieJar->all());
    });
    
  3. Check Profiler Data:

    $this->browser()
        ->withProfiling()
        ->visit('/slow-endpoint')
        ->use(function (RequestDataCollector $collector) {
            echo $collector->getResponseTime();
        });
    
  4. Enable Browser Extension Artifacts:

    • The BrowserExtension auto-saves screenshots/source on test failures. Configure the output directory via:
      BROWSER_SOURCE_DIR=/path/to/custom/dir
      

Extension Points

  1. Custom Browser Classes: Extend KernelBrowser or PantherBrowser to add domain logic:

    class AdminBrowser extends KernelBrowser
    {
        public function loginAsAdmin()
        {
            return $this
                ->visit('/admin/login')
                ->fillField('email', 'admin@example.com')
                ->fillField('password', 'admin')
                ->click('Login');
        }
    }
    
  2. Override Default Assertions: Use PHPUnit’s @method annotations to document custom methods:

    /**
     * @method static self assertAdminPanelVisible()
     */
    class AdminTestBrowser extends KernelBrowser
    {
        public function assertAdminPanelVisible()
        {
            $this->assertSeeElement('#admin-panel');
        }
    }
    
  3. Hook into Browser Lifecycle: Use the use() method to inject logic before/after actions:

    $this->browser()->use(function (Browser $browser) {
        $browser->getClient()->getCookieJar()->clear();
    });
    
  4. Mock External Services: Combine with Symfony’s HTTP client for mocking APIs:

    $this->browser()
        ->use(function (Client $client) {
            $client->addHandler(new MockApiHandler());
        })
        ->visit('/api-dependent-page');
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope