Compare commits

...

3 Commits

Author SHA1 Message Date
Michael B. Gale f56d0ec51b Add hasMessage to RecordingLogger 2026-02-24 20:45:41 +00:00
Michael B. Gale 33edb83959 Replace getRecordingLogger implementation with RecordingLogger 2026-02-24 20:40:41 +00:00
Michael B. Gale 33276bfbdb Add assertNotLogged test helper 2026-02-24 20:36:24 +00:00
+59 -42
View File
@@ -157,8 +157,8 @@ export interface LoggedMessage {
export class RecordingLogger implements Logger {
messages: LoggedMessage[] = [];
groups: string[] = [];
unfinishedGroups: Set<string> = new Set();
readonly groups: string[] = [];
readonly unfinishedGroups: Set<string> = new Set();
private currentGroup: string | undefined = undefined;
constructor(private readonly logToConsole: boolean = true) {}
@@ -172,6 +172,19 @@ export class RecordingLogger implements Logger {
}
}
/**
* Checks whether the logged messages contain `messageOrRegExp`.
*
* If `messageOrRegExp` is a string, this function returns true as long as
* `messageOrRegExp` appears as part of one of the `messages`.
*
* If `messageOrRegExp` is a regular expression, this function returns true as long as
* one of the `messages` matches `messageOrRegExp`.
*/
hasMessage(messageOrRegExp: string | RegExp): boolean {
return hasLoggedMessage(this.messages, messageOrRegExp);
}
isDebug() {
return true;
}
@@ -210,41 +223,37 @@ export function getRecordingLogger(
messages: LoggedMessage[],
{ logToConsole }: { logToConsole?: boolean } = { logToConsole: true },
): Logger {
return {
debug: (message: string) => {
messages.push({ type: "debug", message });
if (logToConsole) {
// eslint-disable-next-line no-console
console.debug(message);
}
},
info: (message: string) => {
messages.push({ type: "info", message });
if (logToConsole) {
// eslint-disable-next-line no-console
console.info(message);
}
},
warning: (message: string | Error) => {
messages.push({ type: "warning", message });
if (logToConsole) {
// eslint-disable-next-line no-console
console.warn(message);
}
},
error: (message: string | Error) => {
messages.push({ type: "error", message });
if (logToConsole) {
// eslint-disable-next-line no-console
console.error(message);
}
},
isDebug: () => true,
startGroup: () => undefined,
endGroup: () => undefined,
};
const logger = new RecordingLogger(logToConsole);
logger.messages = messages;
return logger;
}
/**
* Checks whether `messages` contains `messageOrRegExp`.
*
* If `messageOrRegExp` is a string, this function returns true as long as
* `messageOrRegExp` appears as part of one of the `messages`.
*
* If `messageOrRegExp` is a regular expression, this function returns true as long as
* one of the `messages` matches `messageOrRegExp`.
*/
function hasLoggedMessage(
messages: LoggedMessage[],
messageOrRegExp: string | RegExp,
): boolean {
const check = (val: string) =>
typeof messageOrRegExp === "string"
? val.includes(messageOrRegExp)
: messageOrRegExp.test(val);
return messages.some(
(msg) => typeof msg.message === "string" && check(msg.message),
);
}
/**
* Checks that `messages` contains all of `expectedMessages`.
*/
export function checkExpectedLogMessages(
t: ExecutionContext<any>,
messages: LoggedMessage[],
@@ -253,13 +262,7 @@ export function checkExpectedLogMessages(
const missingMessages: string[] = [];
for (const expectedMessage of expectedMessages) {
if (
!messages.some(
(msg) =>
typeof msg.message === "string" &&
msg.message.includes(expectedMessage),
)
) {
if (!hasLoggedMessage(messages, expectedMessage)) {
missingMessages.push(expectedMessage);
}
}
@@ -276,6 +279,20 @@ export function checkExpectedLogMessages(
}
}
/**
* Asserts that `message` should not have been logged to `logger`.
*/
export function assertNotLogged(
t: ExecutionContext<any>,
logger: RecordingLogger,
message: string | RegExp,
) {
t.false(
logger.hasMessage(message),
`'${message}' should not have been logged, but was.`,
);
}
/**
* Initialises a recording logger and calls `body` with it.
*