Harden verify-work checkpoint rendering
This commit is contained in:
@@ -136,6 +136,12 @@ describe('dispatcher error paths', () => {
|
||||
assert.ok(result.error.includes('Unknown todo subcommand'), `Expected "Unknown todo subcommand" in stderr, got: ${result.error}`);
|
||||
});
|
||||
|
||||
test('uat unknown subcommand errors', () => {
|
||||
const result = runGsdTools('uat bogus', tmpDir);
|
||||
assert.strictEqual(result.success, false, 'Should exit non-zero');
|
||||
assert.ok(result.error.includes('Unknown uat subcommand'), `Expected "Unknown uat subcommand" in stderr, got: ${result.error}`);
|
||||
});
|
||||
|
||||
// Unknown subcommand: init
|
||||
test('init unknown workflow errors', () => {
|
||||
const result = runGsdTools('init bogus', tmpDir);
|
||||
|
||||
@@ -14,6 +14,7 @@ const {
|
||||
requireSafePath,
|
||||
scanForInjection,
|
||||
sanitizeForPrompt,
|
||||
sanitizeForDisplay,
|
||||
safeJsonParse,
|
||||
validatePhaseNumber,
|
||||
validateFieldName,
|
||||
@@ -244,6 +245,19 @@ describe('sanitizeForPrompt', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('sanitizeForDisplay', () => {
|
||||
test('removes protocol leak lines', () => {
|
||||
const input = 'Visible line\nuser to=all:final code something bad\nAnother line';
|
||||
const result = sanitizeForDisplay(input);
|
||||
assert.equal(result, 'Visible line\nAnother line');
|
||||
});
|
||||
|
||||
test('keeps normal user-facing copy intact', () => {
|
||||
const input = 'Type `pass` or describe what\\\'s wrong.';
|
||||
assert.equal(sanitizeForDisplay(input), input);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Shell Safety ───────────────────────────────────────────────────────────
|
||||
|
||||
describe('validateShellArg', () => {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* GSD Tools Tests - UAT Audit
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const { test, describe, beforeEach, afterEach } = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const fs = require('fs');
|
||||
@@ -324,3 +326,83 @@ All checks passed.
|
||||
assert.strictEqual(output.summary.total_files, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('uat render-checkpoint', () => {
|
||||
let tmpDir;
|
||||
let uatPath;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = createTempProject();
|
||||
const phaseDir = path.join(tmpDir, '.planning', 'phases', '01-test-phase');
|
||||
fs.mkdirSync(phaseDir, { recursive: true });
|
||||
uatPath = path.join(phaseDir, '01-UAT.md');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup(tmpDir);
|
||||
});
|
||||
|
||||
test('renders the current checkpoint as raw output', () => {
|
||||
fs.writeFileSync(uatPath, `---
|
||||
status: testing
|
||||
phase: 01-test-phase
|
||||
---
|
||||
|
||||
## Current Test
|
||||
|
||||
number: 2
|
||||
name: Submit form validation
|
||||
expected: |
|
||||
Empty submit keeps controls visible.
|
||||
Validation error copy is shown.
|
||||
awaiting: user response
|
||||
`);
|
||||
|
||||
const result = runGsdTools(['uat', 'render-checkpoint', '--file', '.planning/phases/01-test-phase/01-UAT.md', '--raw'], tmpDir);
|
||||
assert.strictEqual(result.success, true, `render-checkpoint failed: ${result.error}`);
|
||||
assert.ok(result.output.includes('**Test 2: Submit form validation**'));
|
||||
assert.ok(result.output.includes('Empty submit keeps controls visible.'));
|
||||
assert.ok(result.output.includes("Type `pass` or describe what's wrong."));
|
||||
});
|
||||
|
||||
test('strips protocol leak lines from current test copy', () => {
|
||||
fs.writeFileSync(uatPath, `---
|
||||
status: testing
|
||||
phase: 01-test-phase
|
||||
---
|
||||
|
||||
## Current Test
|
||||
|
||||
number: 6
|
||||
name: Locale copy
|
||||
expected: |
|
||||
English strings render correctly.
|
||||
user to=all:final code 彩票平台招商 pass
|
||||
Chinese strings render correctly.
|
||||
awaiting: user response
|
||||
`);
|
||||
|
||||
const result = runGsdTools(['uat', 'render-checkpoint', '--file', '.planning/phases/01-test-phase/01-UAT.md', '--raw'], tmpDir);
|
||||
assert.strictEqual(result.success, true, `render-checkpoint failed: ${result.error}`);
|
||||
assert.ok(!result.output.includes('user to=all:final code'));
|
||||
assert.ok(!result.output.includes('彩票平台'));
|
||||
assert.ok(result.output.includes('English strings render correctly.'));
|
||||
assert.ok(result.output.includes('Chinese strings render correctly.'));
|
||||
});
|
||||
|
||||
test('fails when testing is already complete', () => {
|
||||
fs.writeFileSync(uatPath, `---
|
||||
status: complete
|
||||
phase: 01-test-phase
|
||||
---
|
||||
|
||||
## Current Test
|
||||
|
||||
[testing complete]
|
||||
`);
|
||||
|
||||
const result = runGsdTools(['uat', 'render-checkpoint', '--file', '.planning/phases/01-test-phase/01-UAT.md'], tmpDir);
|
||||
assert.strictEqual(result.success, false, 'Should fail when no current test exists');
|
||||
assert.ok(result.error.includes('already complete'));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user