Files
gstack/test/build-script-shell-compat.test.ts
T
Garry Tan f5c2fee3a9 test: wave coverage for sanitizer, link_or_copy, build script, doc drift
Four new test files (29 cases total):

browse/test/server-sanitize-surrogates.test.ts:
  - 11 unit cases for sanitizeLoneSurrogates (passthrough, valid pair,
    lone high/low mid-string, trailing/leading lone, adjacent doubles,
    pair-then-lone, lone-then-pair, empty)
  - 2 bug-repro tests pinning the regression intent (UTF-8 round-trip,
    JSON.parse round-trip with codepoint assertion)
  - 4 wiring invariants asserting the architectural choke points stay
    intact (handleCommandInternalImpl rename, central sanitization
    line, sanitizeReplacer function exists, SSE producers stringify
    with replacer)
  Function extracted from server.ts via regex + eval'd in test scope
  so no production-code export is needed.

test/setup-windows-fallback.test.ts:
  - Static invariant (D7): zero raw `ln` calls outside the
    _link_or_copy helper body and comments
  - Helper-existence assertions
  - 4-cell behavior matrix (file/dir × Windows/Unix) via awk-style
    helper extraction + bash -c sourcing
  - Windows-note printer registration check
  Mirrors test/setup-conductor-worktree.test.ts patterns.

test/build-script-shell-compat.test.ts:
  - Regex assertion that package.json scripts.* contain no bash brace
    groups (Bun-Windows-hostile)
  - Subshell-precedence check for `.version` redirects
  Strips single-quoted strings before regexing so embedded JS code
  inside echo '...' doesn't false-positive.

test/docs-config-keys.test.ts:
  - DEPRECATED_KEYS denylist scanned across docs/**/*.md
  - Round-trip test for `gstack-config get artifacts_sync_mode`
  Defends the v1.27.0.0 rename from doc drift.

Updates to two existing tests:
  - test/setup-conductor-worktree.test.ts: expect `_link_or_copy`
    instead of `ln -snf` at the Conductor-worktree guard call site
  - test/gen-skill-docs.test.ts: same swap at three assertion sites
    (Codex section, Claude link_claude_skill_dirs body, Codex
    link_codex_skill_dirs body)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 14:02:10 -07:00

41 lines
1.6 KiB
TypeScript

import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
const ROOT = path.resolve(import.meta.dir, '..');
const PKG = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf-8')) as {
scripts: Record<string, string>;
};
// Strip single-quoted strings so JS code emitted as `echo '{ ... }'` doesn't
// trip the shell-brace-group check. Conservative: only `'...'` segments.
function stripSingleQuoted(s: string): string {
return s.replace(/'[^']*'/g, "''");
}
describe('package.json build scripts — POSIX shell compat (D-1460)', () => {
// Bun's Windows shell parser doesn't grok bash brace groups `{ cmd; }`.
// Subshells `( cmd )` are POSIX-universal. This test prevents regression.
test('no bash brace groups in any npm script', () => {
const offending: { script: string; pattern: string }[] = [];
for (const [name, body] of Object.entries(PKG.scripts)) {
const stripped = stripSingleQuoted(body);
const match = stripped.match(/\{\s+[^}]*;\s*\}/);
if (match) {
offending.push({ script: name, pattern: match[0] });
}
}
expect(offending).toEqual([]);
});
test('every `> path/.version` redirect is preceded by a subshell, not a brace group', () => {
// The original PR #1460 target: package.json line 12 had three of these.
const build = PKG.scripts.build ?? '';
const versionRedirects = [...build.matchAll(/(\([^)]*\)|\{[^}]*\})\s*>\s*\S+\/\.version/g)];
expect(versionRedirects.length).toBeGreaterThan(0);
for (const m of versionRedirects) {
expect(m[1].startsWith('(')).toBe(true);
}
});
});