From 9b286ab3f83bd9ff1e7a67a8ecae21da9477293a Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Fri, 13 Feb 2026 12:42:20 -0800 Subject: [PATCH] test: add 3 tests for stdin 1MB overflow and analyzePhase async method (round 87) - post-edit-format.js: verify MAX_STDIN truncation at 1MB limit - post-edit-typecheck.js: verify MAX_STDIN truncation at 1MB limit - skill-create-output.js: test analyzePhase() returns Promise and writes output --- tests/hooks/hooks.test.js | 35 +++++++++++++++++++++++ tests/scripts/skill-create-output.test.js | 28 ++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/tests/hooks/hooks.test.js b/tests/hooks/hooks.test.js index 568f2964..3f8c1022 100644 --- a/tests/hooks/hooks.test.js +++ b/tests/hooks/hooks.test.js @@ -3446,6 +3446,41 @@ Some random content without the expected ### Context to Load section } })) passed++; else failed++; + // ── Round 87: post-edit-format.js and post-edit-typecheck.js stdin overflow (1MB) ── + console.log('\nRound 87: post-edit-format.js (stdin exceeding 1MB — truncation):'); + + if (await asyncTest('truncates stdin at 1MB limit and still passes through data (post-edit-format)', async () => { + // Send 1.2MB of data — exceeds the 1MB MAX_STDIN limit (lines 14-22) + const payload = 'x'.repeat(1024 * 1024 + 200000); + const result = await runScript(path.join(scriptsDir, 'post-edit-format.js'), payload); + + assert.strictEqual(result.code, 0, 'Should exit 0 even with oversized stdin'); + // Output should be truncated — significantly less than input + assert.ok(result.stdout.length < payload.length, + `stdout (${result.stdout.length}) should be shorter than input (${payload.length})`); + // Output should be approximately 1MB (last accepted chunk may push slightly over) + assert.ok(result.stdout.length <= 1024 * 1024 + 65536, + `stdout (${result.stdout.length}) should be near 1MB, not unbounded`); + assert.ok(result.stdout.length > 0, 'Should still pass through truncated data'); + })) passed++; else failed++; + + console.log('\nRound 87: post-edit-typecheck.js (stdin exceeding 1MB — truncation):'); + + if (await asyncTest('truncates stdin at 1MB limit and still passes through data (post-edit-typecheck)', async () => { + // Send 1.2MB of data — exceeds the 1MB MAX_STDIN limit (lines 16-24) + const payload = 'x'.repeat(1024 * 1024 + 200000); + const result = await runScript(path.join(scriptsDir, 'post-edit-typecheck.js'), payload); + + assert.strictEqual(result.code, 0, 'Should exit 0 even with oversized stdin'); + // Output should be truncated — significantly less than input + assert.ok(result.stdout.length < payload.length, + `stdout (${result.stdout.length}) should be shorter than input (${payload.length})`); + // Output should be approximately 1MB (last accepted chunk may push slightly over) + assert.ok(result.stdout.length <= 1024 * 1024 + 65536, + `stdout (${result.stdout.length}) should be near 1MB, not unbounded`); + assert.ok(result.stdout.length > 0, 'Should still pass through truncated data'); + })) 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 1675b4b0..7b8cdb8a 100644 --- a/tests/scripts/skill-create-output.test.js +++ b/tests/scripts/skill-create-output.test.js @@ -497,6 +497,34 @@ function runTests() { 'Should NOT show 80% — confidence=0 is explicitly provided, not missing'); })) passed++; else failed++; + // ── Round 87: analyzePhase() async method (untested) ── + console.log('\nRound 87: analyzePhase() async method:'); + + if (test('analyzePhase completes without error and writes to stdout', () => { + const output = new SkillCreateOutput('test-repo'); + // analyzePhase is async and calls animateProgress which uses sleep() and + // process.stdout.write/clearLine/cursorTo. In non-TTY environments clearLine + // and cursorTo are undefined, but the code uses optional chaining (?.) to + // handle this safely. We verify it resolves without throwing. + // Capture stdout.write to verify output was produced. + const writes = []; + const origWrite = process.stdout.write; + process.stdout.write = function(str) { writes.push(String(str)); return true; }; + try { + // Call synchronously by accessing the returned promise — we just need to + // verify it doesn't throw during setup. The sleeps total 1.9s so we + // verify the promise is a thenable (async function returns Promise). + const promise = output.analyzePhase({ commits: 42 }); + assert.ok(promise && typeof promise.then === 'function', + 'analyzePhase should return a Promise'); + } finally { + process.stdout.write = origWrite; + } + // Verify that process.stdout.write was called (the header line is written synchronously) + assert.ok(writes.length > 0, 'Should have written output via process.stdout.write'); + assert.ok(writes.some(w => w.includes('Analyzing')), 'Should include "Analyzing" label'); + })) passed++; else failed++; + // Summary console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`); process.exit(failed > 0 ? 1 : 0);