Skip to content

Commit e501089

Browse files
committed
Add TestConsole for capturing console output in tests
Introduces a TestConsole interface and createTestConsole implementation to capture and snapshot console output during testing. This utility enables more robust and isolated testing of code that logs to the console.
1 parent d3d63d0 commit e501089

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

packages/common/test/_deps.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { CreateWebSocket, TimingSafeEqual, WebSocket } from "@evolu/common";
22
import BetterSQLite, { Statement } from "better-sqlite3";
33
import { timingSafeEqual } from "crypto";
44
import { customRandom, urlAlphabet } from "nanoid";
5+
import { Console } from "../src/Console.js";
56
import {
67
createSymmetricCrypto,
78
RandomBytes,
@@ -215,3 +216,102 @@ export const testCreateDummyWebSocket: CreateWebSocket = () => ({
215216
isOpen: constFalse,
216217
[Symbol.dispose]: constVoid,
217218
});
219+
220+
/**
221+
* A test console that captures all console output for snapshot testing.
222+
*
223+
* Use this as a drop-in replacement for `createConsole` in tests where you want
224+
* to capture and verify console output.
225+
*/
226+
export interface TestConsole extends Console {
227+
/**
228+
* Gets all captured console logs. Clears the captured logs after returning
229+
* them.
230+
*/
231+
readonly getLogsSnapshot: () => ReadonlyArray<Array<unknown>>;
232+
233+
/** Clears all captured logs. */
234+
readonly clearLogs: () => void;
235+
}
236+
237+
/**
238+
* Creates a test console that captures all console output for testing.
239+
*
240+
* ### Example
241+
*
242+
* ```ts
243+
* test("console output", () => {
244+
* const testConsole = createTestConsole();
245+
*
246+
* // Use it in place of createConsole()
247+
* const deps = { console: testConsole };
248+
*
249+
* // ... run code that logs to console
250+
*
251+
* expect(testConsole.getLogsSnapshot()).toMatchInlineSnapshot();
252+
* });
253+
* ```
254+
*/
255+
export const createTestConsole = (): TestConsole => {
256+
const logs: Array<Array<unknown>> = [];
257+
258+
return {
259+
enabled: true,
260+
261+
log: (...args) => {
262+
logs.push(args);
263+
},
264+
info: (...args) => {
265+
logs.push(args);
266+
},
267+
warn: (...args) => {
268+
logs.push(args);
269+
},
270+
error: (...args) => {
271+
logs.push(args);
272+
},
273+
debug: (...args) => {
274+
logs.push(args);
275+
},
276+
time: (label) => {
277+
logs.push(["time", label]);
278+
},
279+
timeLog: (label, ...data) => {
280+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
281+
logs.push(["timeLog", label, ...data]);
282+
},
283+
timeEnd: (label) => {
284+
logs.push(["timeEnd", label]);
285+
},
286+
dir: (object, options) => {
287+
logs.push(["dir", object, options]);
288+
},
289+
table: (tabularData, properties) => {
290+
logs.push(["table", tabularData, properties]);
291+
},
292+
count: (label) => {
293+
logs.push(["count", label]);
294+
},
295+
countReset: (label) => {
296+
logs.push(["countReset", label]);
297+
},
298+
assert: (value, message, ...optionalParams) => {
299+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
300+
logs.push(["assert", value, message, ...optionalParams]);
301+
},
302+
trace: (message, ...optionalParams) => {
303+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
304+
logs.push(["trace", message, ...optionalParams]);
305+
},
306+
307+
getLogsSnapshot: () => {
308+
const snapshot = [...logs];
309+
logs.length = 0; // Clear captured logs
310+
return snapshot;
311+
},
312+
313+
clearLogs: () => {
314+
logs.length = 0;
315+
},
316+
};
317+
};

0 commit comments

Comments
 (0)