Files
msd-core/tests/runtime-bridge-sync-smoke.test.cjs
Tom Boucher 23b52f1a14 fix(3597): windows test parity batch — CRLF parsers, ESM file URLs, posix-tmp, bash-only skips, retry bump
Six independent windows-only failure clusters identified from the
windows-22 CI log on 1be0e4e2:

- scripts/command-contract-helpers.cjs: parseFrontmatter split on `\n`
  → on Windows checkout (autocrlf=true) every line carries trailing \r,
  lines.indexOf('---', 1) returns -1, all fields read as missing. Drove
  the bulk of three "67 subtests failed" suite-level errors covering
  workstreams.md, workspace.md, verify-work.md, add-tests.md, etc.
  Fix: split(/\r?\n/).

- tests/enh-3271-sdk-adr-structure.test.cjs: same CRLF pattern — H2
  captures pulled '\r' into headings like "decision\r", breaking
  equality checks on "## Decision" / "## Consequences". Fix: same.

- tests/runtime-bridge-sync-smoke.test.cjs: await import(BRIDGE_PATH)
  passed a Windows absolute path to Node's ESM loader, which rejects
  with "Only URLs with a scheme in: file, data, and node are
  supported." Fix: wrap once at module scope with pathToFileURL.
  pathToFileURL is a no-op for POSIX absolute paths.

- tests/bug-2957-claude-global-postinstall-message.test.cjs: hardcoded
  '/tmp/gsd-test-settings.json' resolved to D:\tmp\... on Windows
  where the parent dir doesn't exist → ENOENT on fs.writeFileSync
  inside finishInstall. Fix: os.tmpdir() + pid suffix.

- tests/bug-2774-worktree-cleanup-workspace-safety.test.cjs: the
  "while/read loop" subtest and the "end-to-end against real git
  worktrees" describe both assert POSIX shell behavior (process
  substitution `< <(...)`, RUNNER~1 8.3-shortname mismatch). Skip on
  win32 with explicit reasons (satisfies the
  no-unconditional-win32-skip guard).

- tests/bug-2838-summary-rescue-gitignored-planning.test.cjs: entire
  describe extracts bash rescue blocks from workflow .md files and
  runs them; the shell contract itself is the test's point. Skip on
  win32 with reason.

- tests/helpers.cjs cleanup(): bumped rmSync retry budget from
  10×100ms to 20×250ms — 1s wasn't enough for Windows Defender's
  deferred handle release; bumping to 5s should absorb the residual
  EBUSY failures observed in bug-1736 / bug-2248 / bug-2698 after the
  first retry bump landed in 1be0e4e2.

Validated: holodeck (ubuntu docker) 11224/0 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 12:03:44 -04:00

104 lines
4.1 KiB
JavaScript

'use strict';
/**
* CJS smoke test for the executeForCjs synchronous primitive (Phase 5.0 #3555).
*
* Verifies that the compiled dist artifact can be required from a CJS context
* and that executeForCjs returns the expected result shape synchronously.
*
* This is the critical end-to-end proof that the primitive works for CJS callers
* — the actual point of Phase 5.0.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const path = require('node:path');
const { pathToFileURL } = require('node:url');
const REPO_ROOT = path.join(__dirname, '..');
const BRIDGE_PATH = path.join(REPO_ROOT, 'sdk', 'dist', 'runtime-bridge-sync', 'index.js');
// Node's ESM loader rejects Windows absolute paths with `import()` — must be a
// file:// URL. pathToFileURL is a no-op for POSIX paths (produces file:///abs/...).
const BRIDGE_URL = pathToFileURL(BRIDGE_PATH).href;
describe('runtime-bridge-sync CJS smoke test', () => {
test('executeForCjs is exported and is a function', async () => {
// Use dynamic import because Node 24 supports require() of ESM but
// the module is ESM (NodeNext output). Dynamic import works in all contexts.
const mod = await import(BRIDGE_URL);
assert.strictEqual(typeof mod.executeForCjs, 'function', 'executeForCjs must be a function');
});
test('executeForCjs returns ok:true for generate-slug (success path)', async () => {
const { executeForCjs } = await import(BRIDGE_URL);
const result = executeForCjs({
registryCommand: 'generate-slug',
registryArgs: ['My Smoke Test Phase'],
legacyCommand: 'generate-slug',
legacyArgs: ['My Smoke Test Phase'],
mode: 'json',
projectDir: '/tmp',
});
// The returned value must be a plain object, not a Promise
assert.strictEqual(typeof result, 'object', 'result must be an object');
assert.ok(!(result instanceof Promise), 'result must not be a Promise');
assert.ok('ok' in result, 'result must have ok property');
assert.strictEqual(result.ok, true, 'expected ok:true');
assert.strictEqual(result.exitCode, 0, 'expected exitCode:0');
assert.ok(result.data != null, 'expected data to be non-null');
const data = result.data;
assert.strictEqual(typeof data, 'object', 'data must be an object');
assert.strictEqual(data.slug, 'my-smoke-test-phase', 'expected slug');
});
test('executeForCjs returns ok:false for unknown command', async () => {
const { executeForCjs } = await import(BRIDGE_URL);
const result = executeForCjs({
registryCommand: '__smoke_test_unknown_command__',
registryArgs: [],
legacyCommand: '__smoke_test_unknown_command__',
legacyArgs: [],
mode: 'json',
projectDir: '/tmp',
});
assert.strictEqual(typeof result, 'object', 'result must be an object');
assert.ok(!(result instanceof Promise), 'result must not be a Promise');
assert.strictEqual(result.ok, false, 'expected ok:false');
assert.ok(result.exitCode !== 0, 'expected non-zero exitCode');
assert.ok('errorKind' in result, 'expected errorKind property');
assert.strictEqual(result.errorKind, 'unknown_command', 'expected unknown_command errorKind');
assert.ok(Array.isArray(result.stderrLines), 'expected stderrLines array');
});
test('executeForCjs result shape matches RuntimeBridgeSyncResult discriminated union', async () => {
const { executeForCjs } = await import(BRIDGE_URL);
// Success shape
const success = executeForCjs({
registryCommand: 'current-timestamp',
registryArgs: ['date'],
legacyCommand: 'current-timestamp',
legacyArgs: ['date'],
mode: 'json',
projectDir: '/tmp',
});
assert.ok('ok' in success, 'success result must have ok');
if (success.ok) {
assert.strictEqual(success.exitCode, 0);
assert.ok('data' in success);
} else {
// current-timestamp might fail if args aren't what it expects; just check shape
assert.ok('errorKind' in success);
assert.ok('stderrLines' in success);
assert.ok(Array.isArray(success.stderrLines));
}
});
});