Troubleshooting
Common issues and their solutions when using Pest Plugin Bridge.
Installation Issues
Playwright Not Found
Symptom: "Playwright is not installed" error
Solution:
npm install playwright
npx playwright install chromiumBrowser Launch Fails
Symptom: Browser fails to start on Linux servers
Solution: Install system dependencies:
npx playwright install-deps chromiumConnection Refused
Symptom: Tests fail with "Connection refused" when trying to reach frontend
Checklist:
- Ensure frontend server is running:
curl http://localhost:3000 - Check the port matches your configuration
- If using
serve(), check server output for errors
Frontend Server Issues
Server Doesn't Start
Symptom: Tests hang waiting for server, or "Frontend server failed to start" error
Common causes:
- Wrong command: Check
npm run devworks manually - Wrong directory: Verify
cwd:path is correct (relative to Laravel root) - Port already in use: Kill existing processes
# Kill process on port 3000
lsof -ti:3000 | xargs kill -9
# Or on Windows
netstat -ano | findstr :3000
taskkill /PID <PID> /FServer Starts But Tests Fail
Symptom: Server starts but bridge() can't connect
Checklist:
- URL in
Bridge::setDefault()matches actual server URL - Server is binding to
0.0.0.0orlocalhost, not just127.0.0.1 - No firewall blocking the port
Custom Ready Pattern Needed
Symptom: Tests start before server is ready
Solution: Use readyWhen() with a pattern matching your server's output:
Bridge::setDefault('http://localhost:3000')
->serve('npm run dev', cwd: '../frontend')
->readyWhen('Your custom pattern');Check your server's console output for a reliable "ready" indicator.
Database Issues
SQLite :memory: Doesn't Work
Symptom: Data created in tests is not visible to API
Cause: Each connection gets its own isolated in-memory database
Solution: Use file-based SQLite:
<!-- phpunit.xml -->
<env name="DB_DATABASE" value="database/database.sqlite"/>RefreshDatabase Breaks Tests
Symptom: Test creates data, API returns empty
Cause: RefreshDatabase wraps tests in transactions that aren't visible to other connections
Solution: Use DatabaseTruncation instead:
// tests/Pest.php
pest()->extends(TestCase::class)
->use(DatabaseTruncation::class)
->in('Browser');Database Assertions Fail But UI Shows Success
Symptom: assertDatabaseHas() fails even though UI shows success
Cause: Browser tests use separate database connections
Solution: Don't mix database assertions with browser tests. Use UI assertions instead:
// Instead of: $this->assertDatabaseHas('users', ['email' => $email]);
// Use:
$this->bridge('/users')->assertSee($email);Form & Input Issues
Form Submits Empty Values
Symptom: Form validation fails with "field required" even though you filled it
Cause: Vue/React's reactive binding (v-model, useState) doesn't see fill() DOM changes
Solution: Use typeSlowly() which triggers real keyboard events:
// Instead of:
->fill('[data-testid="email"]', 'test@example.com')
// Use:
->typeSlowly('[data-testid="email"]', 'test@example.com')First Characters Lost When Typing
Symptom: Input shows "xample.com" instead of "example.com"
Cause: Page not fully ready for input, first keystrokes lost
Solution: Click the field first and/or wait:
$this->bridge('/login')
->waitForEvent('networkidle')
->click('input#email') // Focus first
->typeSlowly('input#email', 'test@example.com', 30);Tests Hang or Timeout
Symptom: Test hangs indefinitely or times out
Cause: Waiting for something that never happens
Solutions:
Use event-based waits instead of fixed delays:
php->waitForEvent('networkidle') // Better than ->wait(2)Add timeout to waits:
php->waitForSelector('[data-testid="result"]', timeout: 5000)Check if element actually exists in the DOM
Authentication Issues
CORS Errors
Symptom: Console shows "Access-Control-Allow-Origin" errors
Solution: Update config/cors.php:
return [
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_origins' => ['http://localhost:3000'],
'supports_credentials' => true, // Important for cookies!
];Cookies Not Sent
Symptom: Authentication works manually but not in tests
Checklist:
- Set
SESSION_DOMAIN=localhostin.env - Add frontend to Sanctum stateful domains:php
// config/sanctum.php 'stateful' => ['localhost:3000'], - Frontend sends credentials with requests:javascript
fetch(url, { credentials: 'include' })
CSRF Token Mismatch (419 Error)
Symptom: POST requests return 419 error
Solutions:
For Sanctum SPA auth: Ensure CSRF cookie is fetched first:
php// Frontend should call this before login await fetch('/sanctum/csrf-cookie', { credentials: 'include' });For token-based auth: Remove
statefulApi()middleware:php// bootstrap/app.php - remove or comment out: // ->withMiddleware(function (Middleware $middleware) { // $middleware->statefulApi(); // })
CI/CD Issues
Checkout Fails in GitHub Actions
Symptom: "The process '/usr/bin/git' failed with exit code 1"
Common causes:
Wrong branch name: Check if repo uses
mainormaster:yamlinputs: branch: default: 'master' # or 'main'Private repository: Add access token:
yaml- uses: actions/checkout@v4 with: repository: your-org/private-repo token: ${{ secrets.REPO_ACCESS_TOKEN }}
Composer Install Fails: PHP Version
Symptom: "Package requires PHP >= 8.4"
Solution: Match PHP version to your dependencies:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4' # Match composer.lock requirementsCheck Requirements Locally
composer show --locked | grep symfonySymfony 8.x requires PHP 8.4+.
MySQL Connection Refused
Symptom: Can't connect to MySQL in CI
Checklist:
- Health check passed (check workflow logs)
- Port mapping is correct (
3306:3306) - Use
DB_HOST=127.0.0.1(notlocalhost) - Credentials match service configuration
SQLite "Database does not exist"
Solution: Create file before migrating:
- run: touch database/database.sqlite
- run: php artisan migrate --forceStill Stuck?
Enable headed mode to see what's happening:
bashPLAYWRIGHT_HEADLESS=false ./vendor/bin/pest tests/BrowserTake screenshots at failure points:
php->screenshot('debug-screenshot')Check Laravel logs:
bashtail -f storage/logs/laravel.logOpen an issue with:
- PHP version (
php -v) - Package versions (
composer show testflowlabs/pest-plugin-bridge) - Minimal reproduction code
- Full error message/stack trace
- PHP version (