Files
orca/tests/e2e/artificial-opencode-active-terminal-scroll.ts
T
Neil 102cbdbda2 Make terminal scroll pressure benchmark diagnose responsive paths (#4846)
* Instrument terminal scroll pressure attempts

* Trace terminal scroll input timing

* Reduce PTY renderer in-flight window

* Revert "Reduce PTY renderer in-flight window"

This reverts commit 86775aeb68.

* Probe alternate scroll paths after slow wheel

* Gate scroll pressure on responsive terminal path

* Address scroll benchmark review cleanup
2026-06-07 18:16:53 -07:00

157 lines
5.6 KiB
TypeScript

import type { Page } from '@stablyai/playwright-test'
export type ActiveTerminalScrollState = {
viewportY: number
scrollTop: number | null
}
export async function scrollActiveTerminalToBottom(page: Page): Promise<void> {
await page.evaluate(() => {
const pane = (() => {
const store = window.__store
const state = store?.getState()
const worktreeId = state?.activeWorktreeId
const tabId =
state?.activeTabType === 'terminal'
? state.activeTabId
: worktreeId
? (state?.activeTabIdByWorktree?.[worktreeId] ?? null)
: null
const manager = tabId ? window.__paneManagers?.get(tabId) : null
const candidate = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
if (!candidate) {
throw new Error('Active terminal pane is unavailable')
}
return candidate
})()
pane.terminal.scrollToBottom()
})
}
export async function scrollActiveTerminalViewportElement(page: Page): Promise<void> {
await page.evaluate(() => {
const pane = (() => {
const store = window.__store
const state = store?.getState()
const worktreeId = state?.activeWorktreeId
const tabId =
state?.activeTabType === 'terminal'
? state.activeTabId
: worktreeId
? (state?.activeTabIdByWorktree?.[worktreeId] ?? null)
: null
const manager = tabId ? window.__paneManagers?.get(tabId) : null
const candidate = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
if (!candidate) {
throw new Error('Active terminal pane is unavailable')
}
return candidate
})()
const viewport = pane.container.querySelector<HTMLElement>('.xterm-viewport')
if (!viewport) {
throw new Error('Active terminal viewport is unavailable')
}
// Why: Linux CI can drop wheel delivery entirely under PTY flood; changing
// the viewport scrollTop exercises xterm's DOM scroll synchronization.
viewport.scrollTop = Math.max(0, viewport.scrollTop - 1200)
viewport.dispatchEvent(new Event('scroll', { bubbles: true }))
})
}
export async function scrollActiveTerminalByApi(page: Page): Promise<void> {
await page.evaluate(() => {
const pane = (() => {
const store = window.__store
const state = store?.getState()
const worktreeId = state?.activeWorktreeId
const tabId =
state?.activeTabType === 'terminal'
? state.activeTabId
: worktreeId
? (state?.activeTabIdByWorktree?.[worktreeId] ?? null)
: null
const manager = tabId ? window.__paneManagers?.get(tabId) : null
const candidate = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
if (!candidate) {
throw new Error('Active terminal pane is unavailable')
}
return candidate
})()
// Why: Linux/Xvfb can lose synthetic wheel/DOM scroll events under flood;
// xterm's public API keeps this probe about viewport responsiveness.
const targetLine = Math.max(0, pane.terminal.buffer.active.viewportY - 20)
pane.terminal.scrollToLine(targetLine)
})
}
export async function dispatchActiveTerminalWheelEvent(page: Page): Promise<void> {
await page.evaluate(() => {
const pane = (() => {
const store = window.__store
const state = store?.getState()
const worktreeId = state?.activeWorktreeId
const tabId =
state?.activeTabType === 'terminal'
? state.activeTabId
: worktreeId
? (state?.activeTabIdByWorktree?.[worktreeId] ?? null)
: null
const manager = tabId ? window.__paneManagers?.get(tabId) : null
const candidate = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
if (!candidate) {
throw new Error('Active terminal pane is unavailable')
}
return candidate
})()
// Why: CI can drop CDP wheel input while the active textarea is focused;
// dispatching on xterm's own surfaces still exercises its user scroll path.
const wheelTargets = [
pane.container.querySelector<HTMLElement>('.xterm'),
pane.container.querySelector<HTMLElement>('.xterm-viewport'),
pane.container.querySelector<HTMLElement>('.xterm-screen')
].filter((target): target is HTMLElement => Boolean(target))
if (wheelTargets.length === 0) {
throw new Error('Active terminal wheel target is unavailable')
}
for (const wheelTarget of wheelTargets) {
wheelTarget.dispatchEvent(
new WheelEvent('wheel', {
bubbles: true,
cancelable: true,
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaY: -1200
})
)
}
})
}
export async function readActiveTerminalScrollState(
page: Page
): Promise<ActiveTerminalScrollState> {
return page.evaluate(() => {
const pane = (() => {
const store = window.__store
const state = store?.getState()
const worktreeId = state?.activeWorktreeId
const tabId =
state?.activeTabType === 'terminal'
? state.activeTabId
: worktreeId
? (state?.activeTabIdByWorktree?.[worktreeId] ?? null)
: null
const manager = tabId ? window.__paneManagers?.get(tabId) : null
const candidate = manager?.getActivePane?.() ?? manager?.getPanes?.()[0] ?? null
if (!candidate) {
throw new Error('Active terminal pane is unavailable')
}
return candidate
})()
const viewport = pane.container.querySelector<HTMLElement>('.xterm-viewport')
return {
viewportY: pane.terminal.buffer.active.viewportY,
scrollTop: viewport?.scrollTop ?? null
}
})
}