From 5107b3669ff2ba75621a8165bdc489d972a8ac97 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Thu, 12 Feb 2026 16:53:06 -0800 Subject: [PATCH] fix: box() off-by-one alignment, add 5 tests for readStdinJson and box alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - skill-create-output.js: fix top border being 1 char narrower than middle/bottom lines (width - title - 5 → width - title - 4) - Add box alignment regression test verifying all lines have equal width - Add 4 readStdinJson tests via subprocess (valid JSON, invalid JSON, empty stdin, nested objects) — last untested exported utility function - All 338 tests passing --- scripts/skill-create-output.js | 2 +- tests/lib/utils.test.js | 45 +++++++++++++++++++++++ tests/scripts/skill-create-output.test.js | 25 +++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/scripts/skill-create-output.js b/scripts/skill-create-output.js index e6274f1f..9ae0ebf9 100644 --- a/scripts/skill-create-output.js +++ b/scripts/skill-create-output.js @@ -38,7 +38,7 @@ const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', // Helper functions function box(title, content, width = 60) { const lines = content.split('\n'); - const top = `${BOX.topLeft}${BOX.horizontal} ${chalk.bold(chalk.cyan(title))} ${BOX.horizontal.repeat(Math.max(0, width - title.length - 5))}${BOX.topRight}`; + const top = `${BOX.topLeft}${BOX.horizontal} ${chalk.bold(chalk.cyan(title))} ${BOX.horizontal.repeat(Math.max(0, width - title.length - 4))}${BOX.topRight}`; const bottom = `${BOX.bottomLeft}${BOX.horizontal.repeat(width - 1)}${BOX.bottomRight}`; const middle = lines.map(line => { const padding = width - 3 - stripAnsi(line).length; diff --git a/tests/lib/utils.test.js b/tests/lib/utils.test.js index 9d1d6cea..b708a1b0 100644 --- a/tests/lib/utils.test.js +++ b/tests/lib/utils.test.js @@ -626,6 +626,51 @@ function runTests() { } })) passed++; else failed++; + // readStdinJson tests (via subprocess — safe hardcoded inputs) + console.log('\nreadStdinJson():'); + + if (test('readStdinJson parses valid JSON from stdin', () => { + const { execSync } = require('child_process'); + const script = 'const u=require("./scripts/lib/utils");u.readStdinJson({timeoutMs:2000}).then(d=>{process.stdout.write(JSON.stringify(d))})'; + const result = execSync( + `echo '{"tool_input":{"command":"ls"}}' | node -e '${script}'`, + { encoding: 'utf8', cwd: path.join(__dirname, '..', '..'), timeout: 5000 } + ); + const parsed = JSON.parse(result); + assert.deepStrictEqual(parsed, { tool_input: { command: 'ls' } }); + })) passed++; else failed++; + + if (test('readStdinJson returns {} for invalid JSON', () => { + const { execSync } = require('child_process'); + const script = 'const u=require("./scripts/lib/utils");u.readStdinJson({timeoutMs:2000}).then(d=>{process.stdout.write(JSON.stringify(d))})'; + const result = execSync( + `echo 'not json' | node -e '${script}'`, + { encoding: 'utf8', cwd: path.join(__dirname, '..', '..'), timeout: 5000 } + ); + assert.deepStrictEqual(JSON.parse(result), {}); + })) passed++; else failed++; + + if (test('readStdinJson returns {} for empty stdin', () => { + const { execSync } = require('child_process'); + const script = 'const u=require("./scripts/lib/utils");u.readStdinJson({timeoutMs:2000}).then(d=>{process.stdout.write(JSON.stringify(d))})'; + const result = execSync( + `echo '' | node -e '${script}'`, + { encoding: 'utf8', cwd: path.join(__dirname, '..', '..'), timeout: 5000 } + ); + assert.deepStrictEqual(JSON.parse(result), {}); + })) passed++; else failed++; + + if (test('readStdinJson handles nested objects', () => { + const { execSync } = require('child_process'); + const script = 'const u=require("./scripts/lib/utils");u.readStdinJson({timeoutMs:2000}).then(d=>{process.stdout.write(JSON.stringify(d))})'; + const result = execSync( + `echo '{"a":{"b":1},"c":[1,2]}' | node -e '${script}'`, + { encoding: 'utf8', cwd: path.join(__dirname, '..', '..'), timeout: 5000 } + ); + const parsed = JSON.parse(result); + assert.deepStrictEqual(parsed, { a: { b: 1 }, c: [1, 2] }); + })) passed++; else failed++; + // Summary console.log('\n=== Test Results ==='); console.log(`Passed: ${passed}`); diff --git a/tests/scripts/skill-create-output.test.js b/tests/scripts/skill-create-output.test.js index dd68f2f2..01713134 100644 --- a/tests/scripts/skill-create-output.test.js +++ b/tests/scripts/skill-create-output.test.js @@ -201,6 +201,31 @@ function runTests() { assert.ok(logs.length > 0, 'Should produce output without crash'); })) passed++; else failed++; + // box() alignment regression test + console.log('\nbox() alignment:'); + + if (test('top, middle, and bottom lines have equal visual width', () => { + const output = new SkillCreateOutput('repo', { width: 40 }); + const logs = captureLog(() => output.instincts([ + { name: 'test', confidence: 0.9 }, + ])); + const combined = logs.join('\n'); + const boxLines = combined.split('\n').filter(l => stripAnsi(l).trim().length > 0); + // Find lines that start with box-drawing characters + const boxDrawn = boxLines.filter(l => { + const s = stripAnsi(l).trim(); + return s.startsWith('\u256D') || s.startsWith('\u2502') || s.startsWith('\u2570'); + }); + if (boxDrawn.length >= 3) { + const widths = boxDrawn.map(l => stripAnsi(l).length); + const firstWidth = widths[0]; + widths.forEach((w, i) => { + assert.strictEqual(w, firstWidth, + `Line ${i} width ${w} should match first line width ${firstWidth}`); + }); + } + })) passed++; else failed++; + // Summary console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`); process.exit(failed > 0 ? 1 : 0);