//! Mock `@paperclover/console/Widget` to make testing easier. import { expect, mock } from "bun:test"; import assert from "node:assert"; import type { Widget } from "../Widget.ts"; process.env.CI = "true"; process.env.FORCE_COLOR = "10"; let buffer = ""; let widgets: MockWidget[] = []; globalThis.setTimeout = (() => { throw new Error("Do not call setTimeout in tests"); }) as any; globalThis.clearTimeout = (() => { throw new Error("Do not call clearTimeout in tests"); }) as any; abstract class MockWidget { abstract format(now: number): string; abstract fps: number; isActive = true; redrawCount = 0; successCalls: string[] = []; errorCalls: (string | Error)[] = []; stopCalls: (string | undefined)[] = []; constructor() { } stop(finalMessage?: string): void { this.stopCalls.push(finalMessage); this.isActive = false; } protected redraw(): void { this.redrawCount++; } success(message: string): void { this.successCalls.push(message); this.isActive = false; } error(message: string | Error): void { this.errorCalls.push(message); this.isActive = false; } get active(): boolean { return this.isActive; } } const warn = console.warn; mock.module(require.resolve("../Widget.ts"), () => ({ writeLine: (line: string) => buffer += line + "\n", errorAllWidgets: () => { warn("errorAllWidgets is not implemented"); }, Widget: MockWidget, })); mock.module("node:fs", () => ({ writeSync: (fd: number, data: string) => { assert(fd === 2, "writeSync must be called with stderr"); buffer += data; }, })); export function reset() { buffer = ""; widgets = []; } export function getBuffer() { return buffer; } export function getWidgets() { return widgets as any; } export function expectCalls(widget: Widget, checks: { successCalls?: string[]; errorCalls?: (string | Error)[]; redraws?: number; stopCalls?: (string | undefined)[]; }) { const mockWidget = widget as unknown as MockWidget; expect({ successCalls: mockWidget.successCalls, errorCalls: mockWidget.errorCalls, redraws: mockWidget.redrawCount, stopCalls: mockWidget.stopCalls, }).toEqual({ successCalls: checks.successCalls ?? [], errorCalls: checks.errorCalls ?? [], redraws: checks.redraws ?? 0, stopCalls: checks.stopCalls ?? [], }); }