#1899·pest

[Bug]: [pest-plugin-browser] assertNoJavaScriptErrors() never fails — errors read back as empty, and not captured at all on app pages

Author: hoczeusCreated Sep 6, 2026Updated Sep 6, 2026

What happened?

assertNoJavaScriptErrors() never fails. A page with a guaranteed uncaught TypeError passes it.

Investigating produced two distinct faults, and the second is the one that matters:

Page under test window.__pestBrowser.jsErrors.length assertNoJavaScriptErrors()
Minimal inline-HTML route 1 — error captured correctly passes ← read bug
Real application page (Vite + Alpine) 0 — error never captured passes

1. The read. On a minimal page the init script captures the error correctly, but assertNoJavaScriptErrors() still passes. Page::javaScriptErrors() does evaluate('window.__pestBrowser.jsErrors || []') and MakesConsoleAssertions then does expect($javaScriptErrors)->toBeEmpty() — whatever evaluate() returns for that array, toBeEmpty() accepts it, even when the array demonstrably has one element.

2. The capture. On a real application page (Vite-loaded modules, Alpine) the same injected error never reaches window.__pestBrowser.jsErrors at all — the array is empty. So even a hand-written guard reading that array directly cannot work on the pages one actually wants to guard.

How to reproduce

php
use Illuminate\Support\Facades\Route;

beforeEach(function (): void {
    Route::get('/__repro', fn () => <<<'HTML'
        <!doctype html><html><head><title>repro</title></head>
        <body>
        <p>hello</p>
        <script>window.__definitelyMissing.boom();</script>
        </body></html>
        HTML);
});

it('the broken script really is in the browser', function (): void {
    visit('/__repro')->assertSourceHas('__definitelyMissing');   // passes
});

it('the error IS captured', function (): void {
    $page = visit('/__repro');
    $page->assertScript('document.readyState', 'complete');
    $page->assertScript('window.__pestBrowser.jsErrors.length', 0);  // FAILS: "but got 1" — correct
});

it('but the assertion does not fail', function (): void {
    visit('/__repro')->assertNoJavaScriptErrors();               // passes — this is the bug
});

Repeat the third test against a page in a real app (Vite + Alpine) and window.__pestBrowser.jsErrors.length is 0 there — fault 2.

What I ruled out

  • assertScript() itself is sound. A control asserting 1 === 999 failed correctly with "...to evaluate to 999 ... but got 1", so the comparison layer is fine and the readings above are trustworthy.
  • Not a timing race on the minimal page. Adding document.readyState === 'complete', waitForEvent('load') and extra round trips changed nothing either way.
  • The script does reach the browser — confirmed with assertSourceHas() in the same run, not inferred.

Why it matters

The assertion reads as coverage while asserting nothing. In one codebase here it accounted for 38 assertions across 11 browser test files — all green, none capable of failing.

Package Version

pestphp/pest-plugin-browser v5.0.1

PHP Version

8.4.23

Laravel Version

12.x

Operating System

macOS (also reproduced on self-hosted Linux CI)

Notes

Filed here because issues are disabled on pestphp/pest-plugin-browser. Related but distinct: #1649 (line numbers missing) presumes errors are detected; #1542 is a different failure mode.