test(terminal): cover reveal repaint and pruned diagnostics

This commit is contained in:
Brennan Benson
2026-08-24 19:13:56 -07:00
parent ee60aaa51a
commit 8fe3db1f8c
4 changed files with 25 additions and 4 deletions
@@ -1,5 +1,6 @@
import type { ManagedPaneInternal, PaneRenderingDiagnostics } from './pane-manager-types'
import { getTerminalWebglAutoDecision } from './terminal-webgl-auto-policy'
import { prunePaneWebglContextLosses } from './pane-webgl-context-loss-policy'
export function collectPaneRenderingDiagnostics(
panes: Map<number, ManagedPaneInternal>
@@ -10,7 +11,7 @@ export function collectPaneRenderingDiagnostics(
gpuRenderingEnabled: pane.gpuRenderingEnabled,
webglAttachmentDeferred: pane.webglAttachmentDeferred,
webglDisabledAfterContextLoss: pane.webglDisabledAfterContextLoss,
webglContextLossesInWindow: pane.webglContextLossTimestamps?.length ?? 0,
webglContextLossesInWindow: prunePaneWebglContextLosses(pane),
webglAttachFailedSinceRecovery: pane.webglAttachFailedSinceRecovery === true,
hasComplexScriptOutput: pane.hasComplexScriptOutput,
terminalWebglAutoDecision: getTerminalWebglAutoDecision(),
@@ -239,6 +239,7 @@ describe('schedulePaneRevealRepaint', () => {
it('reattaches a pane that lost WebGL while hidden when its tab is revealed', () => {
const pane = createPane()
pane.webglDisabledAfterContextLoss = true
pane.webglContextLossTimestamps = [Date.now()]
schedulePaneRevealPresent(() => [pane])
flushFrame()
@@ -246,6 +247,8 @@ describe('schedulePaneRevealRepaint', () => {
expect(pane.webglDisabledAfterContextLoss).toBe(false)
expect(pane.webglAddon).not.toBeNull()
expect(pane.terminal.refresh).toHaveBeenCalledTimes(2)
expect(pane.terminal.refresh).toHaveBeenNthCalledWith(2, 0, 23)
})
})
})
@@ -9,6 +9,12 @@ function recentContextLosses(pane: ManagedPaneInternal, now: number): number[] {
return (pane.webglContextLossTimestamps ?? []).filter((timestamp) => timestamp > cutoff)
}
export function prunePaneWebglContextLosses(pane: ManagedPaneInternal, now = Date.now()): number {
const losses = recentContextLosses(pane, now)
pane.webglContextLossTimestamps = losses
return losses.length
}
export function recordPaneWebglContextLoss(pane: ManagedPaneInternal, now = Date.now()): number {
const losses = recentContextLosses(pane, now)
losses.push(now)
@@ -20,9 +26,7 @@ export function canRetryPaneWebglAfterContextLoss(
pane: ManagedPaneInternal,
now = Date.now()
): boolean {
const losses = recentContextLosses(pane, now)
pane.webglContextLossTimestamps = losses
return losses.length < WEBGL_CONTEXT_LOSS_RETRY_LIMIT
return prunePaneWebglContextLosses(pane, now) < WEBGL_CONTEXT_LOSS_RETRY_LIMIT
}
export function resetPaneWebglContextLosses(pane: ManagedPaneInternal): void {
@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { setTerminalWebglDiagnosticRecorder } from '../../../../shared/terminal-webgl-diagnostics'
import type { ManagedPaneInternal } from './pane-manager-types'
import { resumePaneRendering, suspendPaneRendering } from './pane-rendering-control'
import { collectPaneRenderingDiagnostics } from './pane-rendering-diagnostics'
import { attachWebgl, resetTerminalWebglSuggestion } from './pane-webgl-renderer'
import { rebuildAttachedWebgl } from './pane-webgl-reattach'
@@ -216,4 +217,16 @@ describe('terminal WebGL context recovery', () => {
}
])
})
it('reports only recent context losses in rendering diagnostics', () => {
const now = 1_700_000_000_000
vi.spyOn(Date, 'now').mockReturnValue(now)
const pane = createPane()
pane.webglContextLossTimestamps = [now - 60_001, now - 1_000]
const [diagnostics] = collectPaneRenderingDiagnostics(new Map([[pane.id, pane]]))
expect(diagnostics.webglContextLossesInWindow).toBe(1)
expect(pane.webglContextLossTimestamps).toEqual([now - 1_000])
})
})