console/src/test/widget-mock.ts

104 lines
2.3 KiB
TypeScript
Raw Normal View History

2025-03-14 23:22:22 -07:00
//! Mock `@paperclover/console/Widget` to make testing easier.
2025-06-26 23:43:54 -07:00
import { expect, mock } from "bun:test";
2025-03-14 23:22:22 -07:00
import assert from "node:assert";
import type { Widget } from "../Widget.ts";
2025-06-26 23:43:54 -07:00
process.env.CI = "true";
process.env.FORCE_COLOR = "10";
2025-03-14 23:22:22 -07:00
2025-06-26 23:43:54 -07:00
let buffer = "";
2025-03-14 23:22:22 -07:00
let widgets: MockWidget[] = [];
globalThis.setTimeout = (() => {
2025-06-26 23:43:54 -07:00
throw new Error("Do not call setTimeout in tests");
2025-03-14 23:22:22 -07:00
}) as any;
globalThis.clearTimeout = (() => {
2025-06-26 23:43:54 -07:00
throw new Error("Do not call clearTimeout in tests");
2025-03-14 23:22:22 -07:00
}) as any;
abstract class MockWidget {
2025-06-26 23:43:54 -07:00
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;
}
2025-03-14 23:22:22 -07:00
}
const warn = console.warn;
2025-06-26 23:43:54 -07:00
mock.module(require.resolve("../Widget.ts"), () => ({
writeLine: (line: string) => buffer += line + "\n",
errorAllWidgets: () => {
warn("errorAllWidgets is not implemented");
},
Widget: MockWidget,
2025-03-14 23:22:22 -07:00
}));
2025-06-26 23:43:54 -07:00
mock.module("node:fs", () => ({
writeSync: (fd: number, data: string) => {
assert(fd === 2, "writeSync must be called with stderr");
buffer += data;
},
2025-03-14 23:22:22 -07:00
}));
export function reset() {
2025-06-26 23:43:54 -07:00
buffer = "";
widgets = [];
2025-03-14 23:22:22 -07:00
}
export function getBuffer() {
2025-06-26 23:43:54 -07:00
return buffer;
2025-03-14 23:22:22 -07:00
}
export function getWidgets() {
2025-06-26 23:43:54 -07:00
return widgets as any;
2025-03-14 23:22:22 -07:00
}
export function expectCalls(widget: Widget, checks: {
2025-06-26 23:43:54 -07:00
successCalls?: string[];
errorCalls?: (string | Error)[];
redraws?: number;
stopCalls?: (string | undefined)[];
2025-03-14 23:22:22 -07:00
}) {
2025-06-26 23:43:54 -07:00
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 ?? [],
});
}