From 8ebb47bdd1715c4dbcd8d05b5452ea45af305fc2 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Fri, 20 Mar 2026 03:15:05 -0700 Subject: [PATCH] fix: normalize windows bash test harness --- tests/hooks/detect-project-worktree.test.js | 6 +++--- tests/hooks/hooks.test.js | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/hooks/detect-project-worktree.test.js b/tests/hooks/detect-project-worktree.test.js index 1add402e..106898a9 100644 --- a/tests/hooks/detect-project-worktree.test.js +++ b/tests/hooks/detect-project-worktree.test.js @@ -12,7 +12,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('fs'); const os = require('os'); -const { execSync } = require('child_process'); +const { execFileSync, execSync } = require('child_process'); let passed = 0; let failed = 0; @@ -52,7 +52,7 @@ function toBashPath(filePath) { } function runBash(command, options = {}) { - return execSync(`bash -lc '${command.replace(/'/g, "'\\''")}'`, options).toString().trim(); + return execFileSync('bash', ['-lc', command], options).toString().trim(); } const repoRoot = path.resolve(__dirname, '..', '..'); @@ -209,7 +209,7 @@ test('detect-project.sh sets PROJECT_NAME and non-global PROJECT_ID for worktree echo "PROJECT_ID=\${PROJECT_ID}" `; - const result = execSync(`bash -lc '${script.replace(/'/g, "'\\''")}'`, { + const result = execFileSync('bash', ['-lc', script], { cwd: worktreeDir, timeout: 10000, env: { diff --git a/tests/hooks/hooks.test.js b/tests/hooks/hooks.test.js index fe5d7e0e..e192af2c 100644 --- a/tests/hooks/hooks.test.js +++ b/tests/hooks/hooks.test.js @@ -20,6 +20,19 @@ function toBashPath(filePath) { .replace(/\\/g, '/'); } +function fromBashPath(filePath) { + if (process.platform !== 'win32') { + return filePath; + } + + const match = String(filePath).match(/^\/([A-Za-z])\/(.*)$/); + if (!match) { + return filePath; + } + + return `${match[1].toUpperCase()}:\\${match[2].replace(/\//g, '\\')}`; +} + function sleepMs(ms) { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); } @@ -2343,8 +2356,9 @@ async function runTests() { assert.strictEqual(code, 0, `detect-project should source cleanly, stderr: ${stderr}`); const [projectId, projectDir] = stdout.trim().split(/\r?\n/); + const nativeProjectDir = fromBashPath(projectDir); const registryPath = path.join(homeDir, '.claude', 'homunculus', 'projects.json'); - const projectMetadataPath = path.join(projectDir, 'project.json'); + const projectMetadataPath = path.join(nativeProjectDir, 'project.json'); assert.ok(projectId, 'detect-project should emit a project id'); assert.ok(fs.existsSync(registryPath), 'projects.json should be created'); @@ -2352,11 +2366,12 @@ async function runTests() { const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8')); const metadata = JSON.parse(fs.readFileSync(projectMetadataPath, 'utf8')); + const nativeMetadataRoot = fromBashPath(metadata.root); assert.ok(registry[projectId], 'registry should contain the detected project'); assert.strictEqual(metadata.id, projectId, 'project.json should include the detected id'); assert.strictEqual(metadata.name, path.basename(repoDir), 'project.json should include the repo name'); - assert.strictEqual(fs.realpathSync(metadata.root), fs.realpathSync(repoDir), 'project.json should include the repo root'); + assert.strictEqual(fs.realpathSync(nativeMetadataRoot), fs.realpathSync(repoDir), 'project.json should include the repo root'); assert.strictEqual(metadata.remote, 'https://github.com/example/ecc-test.git', 'project.json should include the sanitized remote'); assert.ok(metadata.created_at, 'project.json should include created_at'); assert.ok(metadata.last_seen, 'project.json should include last_seen');