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 Setup

  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 Class:

    use PHPUnit\Framework\TestCase;
    use Zenstruck\Browser\Test\HasBrowser;
    
    class MyTest extends TestCase
    {
        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. KernelBrowser for API Testing

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

2. PantherBrowser for JavaScript

public function testDynamicContent()
{
    $this->pantherBrowser()
        ->visit('/dashboard')
        ->waitForElementVisible('#user-menu')
        ->click('#user-menu')
        ->assertSee('Logout');
}

3. Authentication Flow

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

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

4. Combining with Foundry

public function testWithFoundry()
{
    $post = PostFactory::new()->create(['title' => 'Test Post']);

    $this->browser()
        ->visit("/posts/{$post->id}")
        ->assertSeeIn('h1', 'Test Post');
}

Integration Tips

  • Environment Configuration: Set BROWSER_SOURCE_DIR to customize where screenshots/sources are saved:

    export BROWSER_SOURCE_DIR=./var/browser
    
  • Profiling: Enable globally in phpunit.xml:

    <php>
        <server name="KERNEL_DEBUG" value="1"/>
    </php>
    
  • Exception Handling: Use throwExceptions() when testing error cases:

    $this->browser()
        ->throwExceptions()
        ->visit('/invalid-route')
        ->expectException(NotFoundHttpException::class);
    

Gotchas and Tips

Pitfalls

  1. Authentication Quirks:

    • If you see LogicException: Cannot create the remember-me cookie, call withProfiling() before the request or enable the profiler globally.
  2. PantherBrowser Slowness:

    • Panther tests are significantly slower. Use KernelBrowser for non-JS endpoints.
  3. Redirect Handling:

    • By default, redirects are followed. Use interceptRedirects() to test redirect responses directly.
  4. JMESPath Dependencies:

    • Requires mtdowling/jmespath.php for JSON assertions. Install it manually if missing:
      composer require --dev mtdowling/jmespath.php
      

Debugging Tips

  • Save Sources: Use saveSource('filename.html') to debug failed tests. Artifacts are saved to var/browser/source by default.

  • Dump Data:

    $this->browser()->visit('/page')->dump('h1'); // Dumps the h1 element
    $this->browser()->visit('/api')->dd('data.*.id'); // Dumps and dies on JSON data
    
  • Cookie Management: Access the cookie jar directly:

    $this->browser()->use(function($cookieJar) {
        $cookieJar->expire('MOCKSESSID');
    });
    

Extension Points

  1. Custom Assertions: Extend the Browser class to add domain-specific assertions:

    class CustomBrowser extends Browser
    {
        public function assertCustomCondition()
        {
            return $this->assertSee('Expected Text');
        }
    }
    
  2. Override Defaults: Set environment variables to change defaults:

    export BROWSER_CATCH_EXCEPTIONS=false  # Disable exception catching
    export BROWSER_FOLLOW_REDIRECTS=false  # Disable redirect following
    
  3. Custom Data Collectors: Use the use() method to interact with Symfony's data collectors:

    $this->browser()->use(function($collector) {
        $queries = $collector->getQueries();
    });
    

Pro Tips

  • Test Data Setup: Combine with zenstruck/foundry for seamless test data management:

    $user = UserFactory::new()->create();
    $this->browser()->actingAs($user)->visit('/dashboard');
    
  • API Testing: Use HttpOptions for complex requests:

    $this->browser()
        ->post('/api', HttpOptions::json(['data' => 'value'])
            ->withHeader('Authorization', 'Bearer token'));
    
  • Performance: Disable kernel reboot for faster tests (if stateful tests aren't needed):

    $this->browser()->disableReboot();
    
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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views