import { assert, assertEquals } from "@std/assert"; import Logger from "../lib/logger.ts"; Deno.test("Logger callerLevel - Caller Information Filtering - should include caller info for error when callerLevel is warn", () => { const logger = new Logger({ callerLevel: "warn" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.error("test message"); // Parse JSON output and check for caller info const logEntry = JSON.parse(capturedOutput); assert( logEntry.callerFile, "Should include callerFile for error level", ); assert( typeof logEntry.callerLine === "number", "Should include callerLine for error level", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Caller Information Filtering - should include caller info for warn when callerLevel is warn", () => { const logger = new Logger({ callerLevel: "warn" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.warn("test message"); // Parse JSON output and check for caller info const logEntry = JSON.parse(capturedOutput); assert( logEntry.callerFile, "Should include callerFile for warn level", ); assert( typeof logEntry.callerLine === "number", "Should include callerLine for warn level", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Caller Information Filtering - should NOT include caller info for info when callerLevel is warn", () => { const logger = new Logger({ callerLevel: "warn" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.info("test message"); // Parse JSON output and check for absence of caller info const logEntry = JSON.parse(capturedOutput); assertEquals( logEntry.callerFile, undefined, "Should NOT include callerFile for info level", ); assertEquals( logEntry.callerLine, undefined, "Should NOT include callerLine for info level", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Caller Information Filtering - should NOT include caller info for debug when callerLevel is warn", () => { const logger = new Logger({ callerLevel: "warn", level: "debug" }); // Set level to debug to ensure debug messages are logged // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.debug("test message"); // Parse JSON output and check for absence of caller info const logEntry = JSON.parse(capturedOutput); assertEquals( logEntry.callerFile, undefined, "Should NOT include callerFile for debug level", ); assertEquals( logEntry.callerLine, undefined, "Should NOT include callerLine for debug level", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Caller Information Filtering - should include caller info for all levels when callerLevel is debug", () => { const logger = new Logger({ callerLevel: "debug", level: "debug" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { // Test each level const levels = ["error", "warn", "info", "debug"]; for (const level of levels) { logger[level]("test message"); const logEntry = JSON.parse(capturedOutput); assert( logEntry.callerFile, `Should include callerFile for ${level} level`, ); assert( typeof logEntry.callerLine === "number", `Should include callerLine for ${level} level`, ); } } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Caller Information Filtering - should NOT include caller info for any level when callerLevel is silent", () => { const logger = new Logger({ callerLevel: "silent", level: "debug" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { // Test each level const levels = ["error", "warn", "info", "debug"]; for (const level of levels) { logger[level]("test message"); const logEntry = JSON.parse(capturedOutput); assertEquals( logEntry.callerFile, undefined, `Should NOT include callerFile for ${level} level`, ); assertEquals( logEntry.callerLine, undefined, `Should NOT include callerLine for ${level} level`, ); } } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Simple Formatter with callerLevel - should format correctly without caller info when excluded", () => { const logger = new Logger({ format: "simple", callerLevel: "error" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.info("test message"); // Should not contain caller info pattern assert( !capturedOutput.includes("unknown"), "Should not include caller placeholder", ); assert( !capturedOutput.includes(".js:"), "Should not include file:line pattern", ); // Should still contain other parts assert(capturedOutput.includes("INFO"), "Should include log level"); assert( capturedOutput.includes("test message"), "Should include message", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Simple Formatter with callerLevel - should format correctly with caller info when included", () => { const logger = new Logger({ format: "simple", callerLevel: "info" }); // Mock console.log to capture output const originalLog = console.log; let capturedOutput = ""; console.log = (message) => { capturedOutput = message; }; try { logger.info("test message"); // Should contain caller info pattern assert( capturedOutput.includes(".js:"), "Should include file:line pattern", ); assert(capturedOutput.includes("INFO"), "Should include log level"); assert( capturedOutput.includes("test message"), "Should include message", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Performance Considerations - should not call getCallerInfo when caller info is not needed", () => { const logger = new Logger({ callerLevel: "error" }); // Spy on getCallerInfo method let getCallerInfoCalled = false; const originalGetCallerInfo = logger.getCallerInfo; logger.getCallerInfo = function () { getCallerInfoCalled = true; return originalGetCallerInfo.call(this); }; // Mock console.log to prevent actual output const originalLog = console.log; console.log = () => {}; try { logger.info("test message"); assertEquals( getCallerInfoCalled, false, "getCallerInfo should not be called for info level when callerLevel is error", ); } finally { console.log = originalLog; } }); Deno.test("Logger callerLevel - Performance Considerations - should call getCallerInfo when caller info is needed", () => { const logger = new Logger({ callerLevel: "warn" }); // Spy on getCallerInfo method let getCallerInfoCalled = false; const originalGetCallerInfo = logger.getCallerInfo; logger.getCallerInfo = function () { getCallerInfoCalled = true; return originalGetCallerInfo.call(this); }; // Mock console.log to prevent actual output const originalLog = console.log; console.log = () => {}; try { logger.error("test message"); assertEquals( getCallerInfoCalled, true, "getCallerInfo should be called for error level when callerLevel is warn", ); } finally { console.log = originalLog; } });