From 03056d279d4f0c19a645f395bc752f6f977f7a1b Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Wed, 26 Mar 2025 22:19:24 +0000 Subject: [PATCH] update --- package.json | 3 +- test/test.logger.ts | 144 ++++++++++++++++++++++++++++++++++++++++++++ ts/logger.ts | 132 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 test/test.logger.ts create mode 100644 ts/logger.ts diff --git a/package.json b/package.json index d9d876e..3454d52 100644 --- a/package.json +++ b/package.json @@ -56,5 +56,6 @@ "mongodb-memory-server", "puppeteer" ] - } + }, + "packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6" } diff --git a/test/test.logger.ts b/test/test.logger.ts new file mode 100644 index 0000000..16a153f --- /dev/null +++ b/test/test.logger.ts @@ -0,0 +1,144 @@ +import { tap, expect } from '@push.rocks/tapbundle'; +import { Logger } from '../ts/logger.js'; + +// Create a Logger instance for testing +const logger = new Logger(); + +tap.test('should create a logger instance', async () => { + expect(logger instanceof Logger).toBeTruthy(); +}); + +tap.test('should log messages with different log levels', async () => { + // We're not testing console output directly, just ensuring no errors + logger.log('Regular log message'); + logger.error('Error message'); + logger.warn('Warning message'); + logger.success('Success message'); + + // Just assert that the test runs without errors + expect(true).toBeTruthy(); +}); + +tap.test('should create a logbox with title, content, and end', async () => { + // Just ensuring no errors occur + logger.logBoxTitle('Test Box', 40); + logger.logBoxLine('This is a test line'); + logger.logBoxEnd(); + + // Just assert that the test runs without errors + expect(true).toBeTruthy(); +}); + +tap.test('should handle width persistence between logbox calls', async () => { + logger.logBoxTitle('Width Test', 45); + + // These should use the width from the title + logger.logBoxLine('Line 1'); + logger.logBoxLine('Line 2'); + logger.logBoxEnd(); + + let errorThrown = false; + + try { + // This should work fine after the reset in logBoxEnd + logger.logBoxTitle('New Box', 30); + logger.logBoxLine('New line'); + logger.logBoxEnd(); + } catch (error) { + errorThrown = true; + } + + expect(errorThrown).toBeFalsy(); +}); + +tap.test('should throw error when using logBoxLine without width', async () => { + let errorThrown = false; + + try { + // Should throw because no width is set + logger.logBoxLine('This should fail'); + } catch (error) { + errorThrown = true; + expect((error as Error).message).toContain('No box width specified'); + } + + expect(errorThrown).toBeTruthy(); +}); + +tap.test('should create a complete logbox in one call', async () => { + // Just ensuring no errors occur + logger.logBox('Complete Box', [ + 'Line 1', + 'Line 2', + 'Line 3' + ], 40); + + // Just assert that the test runs without errors + expect(true).toBeTruthy(); +}); + +tap.test('should handle content that exceeds box width', async () => { + // Just ensuring no errors occur when content is too long + logger.logBox('Truncation Test', [ + 'This line is way too long and should be truncated because it exceeds the available space' + ], 30); + + // Just assert that the test runs without errors + expect(true).toBeTruthy(); +}); + +tap.test('should create dividers with custom characters', async () => { + // Just ensuring no errors occur + logger.logDivider(30); + logger.logDivider(20, '*'); + + // Just assert that the test runs without errors + expect(true).toBeTruthy(); +}); + +tap.test('Logger Demo', async () => { + console.log('\n=== LOGGER DEMO ===\n'); + + // Basic logging + logger.log('Regular log message'); + logger.error('Error message'); + logger.warn('Warning message'); + logger.success('Success message'); + + // Logbox with title, content lines, and end + logger.logBoxTitle('Configuration Loaded', 50); + logger.logBoxLine('SNMP Settings:'); + logger.logBoxLine(' Host: 127.0.0.1'); + logger.logBoxLine(' Port: 161'); + logger.logBoxLine(' Version: 1'); + logger.logBoxEnd(); + + // Complete logbox in one call + logger.logBox('UPS Status', [ + 'Power Status: onBattery', + 'Battery Capacity: 75%', + 'Runtime Remaining: 30 minutes' + ], 45); + + // Logbox with content that's too long for the width + logger.logBox('Truncation Example', [ + 'This line is short enough to fit within the box width', + 'This line is way too long and will be truncated because it exceeds the available space for content within the logbox' + ], 40); + + // Demonstrating logbox width being remembered + logger.logBoxTitle('Width Persistence Example', 60); + logger.logBoxLine('These lines use the width from the title'); + logger.logBoxLine('No need to specify the width again'); + logger.logBoxEnd(); + + // Divider example + logger.log('\nDivider example:'); + logger.logDivider(30); + logger.logDivider(30, '*'); + + expect(true).toBeTruthy(); +}); + +// Export the default tap object +export default tap.start(); \ No newline at end of file diff --git a/ts/logger.ts b/ts/logger.ts new file mode 100644 index 0000000..6361c5d --- /dev/null +++ b/ts/logger.ts @@ -0,0 +1,132 @@ +/** + * A simple logger class that provides consistent formatting for log messages + * including support for logboxes with title, lines, and closing + */ +export class Logger { + private currentBoxWidth: number | null = null; + + /** + * Creates a new Logger instance + */ + constructor() { + this.currentBoxWidth = null; + } + + /** + * Log a message + * @param message Message to log + */ + public log(message: string): void { + console.log(message); + } + + /** + * Log an error message + * @param message Error message to log + */ + public error(message: string): void { + console.error(message); + } + + /** + * Log a warning message with a warning emoji + * @param message Warning message to log + */ + public warn(message: string): void { + console.warn(`⚠️ ${message}`); + } + + /** + * Log a success message with a checkmark + * @param message Success message to log + */ + public success(message: string): void { + console.log(`✓ ${message}`); + } + + /** + * Log a logbox title and set the current box width + * @param title Title of the logbox + * @param width Width of the logbox (including borders) + */ + public logBoxTitle(title: string, width: number): void { + this.currentBoxWidth = width; + + // Create the title line with appropriate padding + const paddedTitle = ` ${title} `; + const remainingSpace = width - 3 - paddedTitle.length; + + // Title line: ┌─ Title ───┐ + const titleLine = `┌─${paddedTitle}${'─'.repeat(remainingSpace)}┐`; + + console.log(titleLine); + } + + /** + * Log a logbox line + * @param content Content of the line + * @param width Optional width override. If not provided, uses the current box width. + */ + public logBoxLine(content: string, width?: number): void { + const boxWidth = width || this.currentBoxWidth; + + if (!boxWidth) { + throw new Error('No box width specified and no previous box width to use'); + } + + // Calculate the available space for content + const availableSpace = boxWidth - 2; // Account for left and right borders + + if (content.length <= availableSpace - 1) { + // If content fits with at least one space for the right border stripe + const padding = availableSpace - content.length - 1; + console.log(`│ ${content}${' '.repeat(padding)}│`); + } else { + // Content is too long, let it flow out of boundaries. + console.log(`│ ${content}`); + } + } + + /** + * Log a logbox end + * @param width Optional width override. If not provided, uses the current box width. + */ + public logBoxEnd(width?: number): void { + const boxWidth = width || this.currentBoxWidth; + + if (!boxWidth) { + throw new Error('No box width specified and no previous box width to use'); + } + + // Create the bottom border: └────────┘ + console.log(`└${'─'.repeat(boxWidth - 2)}┘`); + + // Reset the current box width + this.currentBoxWidth = null; + } + + /** + * Log a complete logbox with title, content lines, and ending + * @param title Title of the logbox + * @param lines Array of content lines + * @param width Width of the logbox + */ + public logBox(title: string, lines: string[], width: number): void { + this.logBoxTitle(title, width); + + for (const line of lines) { + this.logBoxLine(line); + } + + this.logBoxEnd(); + } + + /** + * Log a divider line + * @param width Width of the divider + * @param character Character to use for the divider (default: ─) + */ + public logDivider(width: number, character: string = '─'): void { + console.log(character.repeat(width)); + } +} \ No newline at end of file