import { assert, assertEquals } from "@std/assert"; import Logger from "../lib/logger.ts"; import { clearCapturedLogs, getCapturedLogs, setupMocks, } from "./helpers/logger-test-helpers.js"; // Setup and teardown for all tests setupMocks(); Deno.test("Logger Internal Error Handling - Formatter Error Handling - should fall back to JSON formatter when custom formatter throws", () => { clearCapturedLogs(); const logger = new Logger({ format: "simple" }); // Replace the simple formatter with one that throws logger.formatters.simple = function () { throw new Error("Custom formatter error"); }; logger.info("test message"); // Should still produce output using JSON formatter fallback assertEquals(getCapturedLogs().length, 1); // Should be valid JSON (fallback to JSON formatter) const logOutput = getCapturedLogs()[0]; const parsed = JSON.parse(logOutput); assertEquals(parsed.msg, "test message"); assert( parsed.formatterError.includes( "Formatter failed: Custom formatter error", ), ); }); Deno.test("Logger Internal Error Handling - Formatter Error Handling - should not crash when formatter returns non-string", () => { clearCapturedLogs(); const logger = new Logger({ format: "simple" }); // Replace formatter with one that returns an object instead of string logger.formatters.simple = function () { return { notAString: true }; }; logger.info("test message"); // Should still produce output (fallback should handle this) assertEquals(getCapturedLogs().length, 1); // Should be valid JSON from fallback const logOutput = getCapturedLogs()[0]; const parsed = JSON.parse(logOutput); assertEquals(parsed.msg, "test message"); }); Deno.test("Logger Internal Error Handling - Formatter Error Handling - should preserve original formatters after error", () => { clearCapturedLogs(); const logger = new Logger({ format: "simple" }); // Temporarily break the formatter const originalSimple = logger.formatters.simple; logger.formatters.simple = function () { throw new Error("Temporary error"); }; logger.info("first message"); // Restore the formatter logger.formatters.simple = originalSimple; logger.info("second message"); // First message should have used fallback, second should work normally assertEquals(getCapturedLogs().length, 2); // First log should be JSON (fallback) JSON.parse(getCapturedLogs()[0]); // This should not throw // Second log should be simple format assert(getCapturedLogs()[1].includes("[INFO ]")); assert(getCapturedLogs()[1].includes("second message")); }); Deno.test("Logger Internal Error Handling - Formatter Error Handling - should handle repeated formatter failures without memory leaks", () => { clearCapturedLogs(); const logger = new Logger({ format: "simple" }); // Break the formatter logger.formatters.simple = function () { throw new Error("Always fails"); }; // Log many times for (let i = 0; i < 100; i++) { logger.info(`message ${i}`); } // Should have produced 100 fallback logs assertEquals(getCapturedLogs().length, 100); // All should be valid JSON (fallback format) getCapturedLogs().forEach((log) => { JSON.parse(log); // This should not throw }); });