fix(desktop): flip e2e assertion + exempt boot-failure from error guard

- large-session-reload: assert exactly 1 burst (was >= 2) — the fix
  eliminates the duplicate re-render, so 1 is the expected count
- boot-failure: add allowErrorBanners() beforeEach — these tests
  deliberately trigger boot errors, so error toasts are expected
- test.ts: export allowErrorBanners() opt-out + reset flag in afterEach
This commit is contained in:
ethernet 2026-07-20 19:49:20 -04:00
parent a84ffb1ba8
commit 95fc08e7d6
3 changed files with 35 additions and 3 deletions

View file

@ -9,7 +9,7 @@
* Prerequisite: `npm run build` must have been run so dist/ exists.
*/
import { test } from './test'
import { allowErrorBanners, test } from './test'
import {
type DeadBackendFixture,
@ -26,6 +26,12 @@ test.afterAll(async () => {
})
test.describe('boot failure with dead backend', () => {
test.beforeEach(() => {
// These tests deliberately trigger boot errors — error banners
// (notifyError → [role="alert"]) are expected, not failures.
allowErrorBanners()
})
test('app shows error state', async () => {
// Inject a fake boot error so the backend resolution "fails" with a
// controlled error message. This is the only reliable way to trigger

View file

@ -337,11 +337,15 @@ test.describe('loading a large previous session', () => {
expect(results, 'render count data should have been collected').not.toBeNull()
if (results) {
// After the fix, the transcript should paint exactly once (1 burst).
// Before the fix, it painted 2-3 times (the "re-renders a few times
// as it loads" bug). This assertion proves the fix works — if it
// ever regresses to >= 2, the test will fail.
expect(
results.bursts,
`expected >= 2 mutation bursts (multiple re-renders during load), ` +
`expected exactly 1 mutation burst (single paint after fix), ` +
`got ${results.bursts}: ${JSON.stringify(results.timeline)}`,
).toBeGreaterThanOrEqual(2)
).toBe(1)
}
})
})

View file

@ -18,6 +18,18 @@ import { test as base, expect, type Page, type ElectronApplication, _electron }
// Track error messages per test so afterEach can assert + report.
const seenErrors: string[] = []
let activePage: Page | null = null
// When true, the afterEach guard skips the error-banner check.
// Set by tests that deliberately trigger error states (e.g. boot-failure).
let errorBannersAllowed = false
/**
* Opt out of the error-banner guard for the current test. Call in
* test.beforeEach or at the top of a test body when error banners are
* expected (e.g. boot-failure tests that deliberately trigger errors).
*/
export function allowErrorBanners(): void {
errorBannersAllowed = true
}
/**
* Install the error-banner guard on a page. Watches for `[role="alert"]`
@ -125,6 +137,16 @@ export const test = base.extend({
// default `page` fixture — Electron tests create their own page via
// app.firstWindow(), so the default `page` fixture is undefined.
base.afterEach(async ({}, testInfo) => {
const wasAllowed = errorBannersAllowed
// Reset for the next test.
errorBannersAllowed = false
if (wasAllowed) {
// Test opted out — clear any collected errors without asserting.
seenErrors.length = 0
return
}
const errors = await collectErrorBanners(activePage)
if (errors.length > 0) {