From e9b19f2ca1a44a9bf34fdfe0fac0c1f5dd4e493f Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Thu, 30 Jul 2026 11:44:43 -0700 Subject: [PATCH] test(mobile): satisfy changed-line quality checks --- .../terminal-webview-mouse-drag.test.ts | 6 +- .../terminal-webview-mouse-test-harness.ts | 67 ++++++++++--------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/mobile/src/terminal/terminal-webview-mouse-drag.test.ts b/mobile/src/terminal/terminal-webview-mouse-drag.test.ts index fadc7e6dbf9..e4fac512873 100644 --- a/mobile/src/terminal/terminal-webview-mouse-drag.test.ts +++ b/mobile/src/terminal/terminal-webview-mouse-drag.test.ts @@ -21,7 +21,7 @@ describe('terminal WebView external mouse drag', () => { for (const motion of reports.slice(1, -1)) { expect(motion.charCodeAt(3)).toBe(64) } - expect(reports[reports.length - 1]?.charCodeAt(3)).toBe(35) + expect(reports.at(-1)?.charCodeAt(3)).toBe(35) // Motion reports are deduped per cell, so a horizontal drag advances columns. const motionCols = reports.slice(1, -1).map((report) => report.charCodeAt(4)) expect(new Set(motionCols).size).toBe(motionCols.length) @@ -63,7 +63,7 @@ describe('terminal WebView external mouse drag', () => { mouse.dispatchPointer('pointermove', { x: 200, y: 60, button: 0, buttons: 0 }) const reports = mouse.terminalInputBytes().match(DEFAULT_MOUSE_REPORT_RE) ?? [] - expect(reports[reports.length - 1]?.charCodeAt(3)).toBe(35) + expect(reports.at(-1)?.charCodeAt(3)).toBe(35) mouse.clearPostedMessages() mouse.dispatchPointer('pointermove', { x: 240, y: 60, button: 0, buttons: 1 }) @@ -82,6 +82,6 @@ describe('terminal WebView external mouse drag', () => { const reports = mouse.terminalInputBytes().match(DEFAULT_MOUSE_REPORT_RE) ?? [] // Press went to the TUI, so the cancel must not leave the button latched. - expect(reports[reports.length - 1]?.charCodeAt(3)).toBe(35) + expect(reports.at(-1)?.charCodeAt(3)).toBe(35) }) }) diff --git a/mobile/src/terminal/terminal-webview-mouse-test-harness.ts b/mobile/src/terminal/terminal-webview-mouse-test-harness.ts index ac55f892427..5d48af87fd3 100644 --- a/mobile/src/terminal/terminal-webview-mouse-test-harness.ts +++ b/mobile/src/terminal/terminal-webview-mouse-test-harness.ts @@ -1,3 +1,4 @@ +import { runInThisContext } from 'node:vm' import { afterEach, beforeEach, vi, type Mock } from 'vitest' import { XTERM_HTML } from './terminal-webview-html' @@ -105,7 +106,36 @@ function terminalSurface(): HTMLElement { return surface } -function postedMessages(postMessage: PostMessage): Array> { +function dispatchPointer(type: PointerEventType, init: PointerEventInit = {}): void { + const event = new MouseEvent(type, { + bubbles: true, + cancelable: true, + clientX: init.x ?? 40, + clientY: init.y ?? 60, + button: init.button ?? 0, + buttons: init.buttons ?? 0 + }) + // Why: happy-dom's PointerEvent init drops pointerType; grafting it onto a + // MouseEvent exercises the same duck-typed reads the WebView handler does. + Object.defineProperty(event, 'pointerType', { value: init.pointerType ?? 'mouse' }) + terminalSurface().dispatchEvent(event) +} + +function mouseClick(x: number, y: number): void { + dispatchPointer('pointerdown', { x, y, button: 0, buttons: 1 }) + dispatchPointer('pointerup', { x, y, button: 0, buttons: 0 }) +} + +function mouseDrag(x1: number, y1: number, x2: number, y2: number): void { + dispatchPointer('pointerdown', { x: x1, y: y1, button: 0, buttons: 1 }) + const midX = Math.round((x1 + x2) / 2) + const midY = Math.round((y1 + y2) / 2) + dispatchPointer('pointermove', { x: midX, y: midY, button: 0, buttons: 1 }) + dispatchPointer('pointermove', { x: x2, y: y2, button: 0, buttons: 1 }) + dispatchPointer('pointerup', { x: x2, y: y2, button: 0, buttons: 0 }) +} + +function postedMessages(postMessage: PostMessage): Record[] { return postMessage.mock.calls.map(([raw]) => JSON.parse(String(raw)) as Record) } @@ -117,7 +147,7 @@ function terminalInputBytes(postMessage: PostMessage): string { } export function useTerminalMouseWebViewHarness() { - let animationFrames: Array<() => void> + let animationFrames: (() => void)[] let buffer: BufferState let postMessage: PostMessage let registeredWindowListeners: RegisteredWindowListener[] @@ -126,7 +156,7 @@ export function useTerminalMouseWebViewHarness() { function boot(): void { document.body.innerHTML = bodyMarkup() - new Function(iifeSource())() + runInThisContext(iifeSource()) window.dispatchEvent( new MessageEvent('message', { data: JSON.stringify({ type: 'init', cols: 40, rows: 24, initialData: '' }) @@ -139,42 +169,13 @@ export function useTerminalMouseWebViewHarness() { } function activeTerminal(): TerminalStub { - const terminal = terminals[terminals.length - 1] + const terminal = terminals.at(-1) if (!terminal) { throw new Error('terminal missing') } return terminal } - function dispatchPointer(type: PointerEventType, init: PointerEventInit = {}): void { - const event = new MouseEvent(type, { - bubbles: true, - cancelable: true, - clientX: init.x ?? 40, - clientY: init.y ?? 60, - button: init.button ?? 0, - buttons: init.buttons ?? 0 - }) - // Why: happy-dom's PointerEvent init drops pointerType; grafting it onto a - // MouseEvent exercises the same duck-typed reads the WebView handler does. - Object.defineProperty(event, 'pointerType', { value: init.pointerType ?? 'mouse' }) - terminalSurface().dispatchEvent(event) - } - - function mouseClick(x: number, y: number): void { - dispatchPointer('pointerdown', { x, y, button: 0, buttons: 1 }) - dispatchPointer('pointerup', { x, y, button: 0, buttons: 0 }) - } - - function mouseDrag(x1: number, y1: number, x2: number, y2: number): void { - dispatchPointer('pointerdown', { x: x1, y: y1, button: 0, buttons: 1 }) - const midX = Math.round((x1 + x2) / 2) - const midY = Math.round((y1 + y2) / 2) - dispatchPointer('pointermove', { x: midX, y: midY, button: 0, buttons: 1 }) - dispatchPointer('pointermove', { x: x2, y: y2, button: 0, buttons: 1 }) - dispatchPointer('pointerup', { x: x2, y: y2, button: 0, buttons: 0 }) - } - beforeEach(() => { animationFrames = [] buffer = { baseY: 0, type: 'normal', viewportY: 0 }