From 57e1cac2f895aab90e0135dbfed6f8daad52b502 Mon Sep 17 00:00:00 2001 From: Shannon Johnson Date: Tue, 15 Sep 2026 14:00:49 +1000 Subject: [PATCH 1/3] fix: lazy evaluate debug messages to avoid unnecessary truncation calls --- src/cell.js | 8 ++++---- src/debug.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cell.js b/src/cell.js index d1fff67..6ca815e 100644 --- a/src/cell.js +++ b/src/cell.js @@ -133,11 +133,11 @@ class Cell { draw(lineNum, spanningCell) { if (lineNum == 'top') return this.drawTop(this.drawRight); if (lineNum == 'bottom') return this.drawBottom(this.drawRight); - let content = utils.truncate(this.content, 10, this.truncate); if (!lineNum) { - info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`); - } else { - // debug(`${lineNum}-${this.x}: 1x${this.colSpan} RowSpanCell ${content}`); + info(() => { + const content = utils.truncate(this.content, 10, this.truncate); + return `${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`; + }); } let padLen = Math.max(this.height - this.lines.length, 0); let padTop; diff --git a/src/debug.js b/src/debug.js index 6acfb03..00bc33c 100644 --- a/src/debug.js +++ b/src/debug.js @@ -3,7 +3,7 @@ let level = 0; const debug = (msg, min) => { if (level >= min) { - messages.push(msg); + messages.push(typeof msg === 'function' ? msg() : msg); } }; From e8067285d1f1a1d39e32594ca448f2fe67b63f15 Mon Sep 17 00:00:00 2001 From: Shannon Johnson Date: Tue, 15 Sep 2026 14:07:01 +1000 Subject: [PATCH 2/3] test: cover lazy debug messages and multiline cell previews --- test/lazy-debug-test.js | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 test/lazy-debug-test.js diff --git a/test/lazy-debug-test.js b/test/lazy-debug-test.js new file mode 100644 index 0000000..a7f9cf6 --- /dev/null +++ b/test/lazy-debug-test.js @@ -0,0 +1,68 @@ +const debug = require('../src/debug'); +const Table = require('..'); +const utils = require('../src/utils'); + +describe('lazy debug messages', () => { + beforeEach(() => { + debug.setDebugLevel(0); + debug.reset(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + debug.setDebugLevel(0); + debug.reset(); + }); + + describe.each([ + ['warn', debug.WARN], + ['info', debug.INFO], + ['debug', debug.DEBUG], + ])('%s', (method, level) => { + it('does not evaluate messages below the configured level', () => { + debug.setDebugLevel(level - 1); + const message = jest.fn(() => 'lazy message'); + + debug[method](message); + + expect(message).not.toHaveBeenCalled(); + expect(debug.debugMessages()).toEqual([]); + }); + + it('evaluates enabled messages once and preserves string messages', () => { + debug.setDebugLevel(level); + const message = jest.fn(() => 'lazy message'); + + debug[method]('plain message'); + debug[method](message); + + expect(message).toHaveBeenCalledTimes(1); + expect(debug.debugMessages()).toEqual(['plain message', 'lazy message']); + }); + }); + + it.each([0, 1, 2, 3])('only computes cell previews when info logging is enabled (level %i)', (level) => { + const content = 'first line of content\nsecond line of content\nthird line of content'; + const preview = utils.truncate(content, 10, '…'); + const truncate = jest.spyOn(utils, 'truncate'); + const table = new Table({ debug: level, style: { head: [], border: [] } }); + table.push([content]); + + const output = table.toString(); + + expect(output).toBe( + [ + '┌────────────────────────┐', + '│ first line of content │', + '│ second line of content │', + '│ third line of content │', + '└────────────────────────┘', + ].join('\n') + ); + const previews = truncate.mock.calls.filter(([value, width]) => value === content && width === 10); + expect(previews).toHaveLength(level >= debug.INFO ? 1 : 0); + if (level >= debug.INFO) { + expect(table.messages).toContain(`0-0: 1x1 Cell ${preview}`); + } + }); +}); From 3ba404688bb6844f4dc2dc1a5e60056106eb047d Mon Sep 17 00:00:00 2001 From: Shannon Johnson Date: Tue, 15 Sep 2026 14:12:48 +1000 Subject: [PATCH 3/3] Remove additional debug regression tests --- test/lazy-debug-test.js | 68 ----------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 test/lazy-debug-test.js diff --git a/test/lazy-debug-test.js b/test/lazy-debug-test.js deleted file mode 100644 index a7f9cf6..0000000 --- a/test/lazy-debug-test.js +++ /dev/null @@ -1,68 +0,0 @@ -const debug = require('../src/debug'); -const Table = require('..'); -const utils = require('../src/utils'); - -describe('lazy debug messages', () => { - beforeEach(() => { - debug.setDebugLevel(0); - debug.reset(); - }); - - afterEach(() => { - jest.restoreAllMocks(); - debug.setDebugLevel(0); - debug.reset(); - }); - - describe.each([ - ['warn', debug.WARN], - ['info', debug.INFO], - ['debug', debug.DEBUG], - ])('%s', (method, level) => { - it('does not evaluate messages below the configured level', () => { - debug.setDebugLevel(level - 1); - const message = jest.fn(() => 'lazy message'); - - debug[method](message); - - expect(message).not.toHaveBeenCalled(); - expect(debug.debugMessages()).toEqual([]); - }); - - it('evaluates enabled messages once and preserves string messages', () => { - debug.setDebugLevel(level); - const message = jest.fn(() => 'lazy message'); - - debug[method]('plain message'); - debug[method](message); - - expect(message).toHaveBeenCalledTimes(1); - expect(debug.debugMessages()).toEqual(['plain message', 'lazy message']); - }); - }); - - it.each([0, 1, 2, 3])('only computes cell previews when info logging is enabled (level %i)', (level) => { - const content = 'first line of content\nsecond line of content\nthird line of content'; - const preview = utils.truncate(content, 10, '…'); - const truncate = jest.spyOn(utils, 'truncate'); - const table = new Table({ debug: level, style: { head: [], border: [] } }); - table.push([content]); - - const output = table.toString(); - - expect(output).toBe( - [ - '┌────────────────────────┐', - '│ first line of content │', - '│ second line of content │', - '│ third line of content │', - '└────────────────────────┘', - ].join('\n') - ); - const previews = truncate.mock.calls.filter(([value, width]) => value === content && width === 10); - expect(previews).toHaveLength(level >= debug.INFO ? 1 : 0); - if (level >= debug.INFO) { - expect(table.messages).toContain(`0-0: 1x1 Cell ${preview}`); - } - }); -});