mirror of
https://github.com/jarrodwatts/claude-hud.git
synced 2026-05-04 19:42:40 +00:00
Add i18n infrastructure with automatic language detection from system locale (LANG/LC_ALL/LC_MESSAGES) and manual override via config.json. Translates all user-facing HUD labels, status messages, and format strings. English remains the default. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
95 lines
2.9 KiB
JavaScript
95 lines
2.9 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { fileURLToPath } from "node:url";
|
|
import { spawnSync } from "node:child_process";
|
|
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { readFileSync } from "node:fs";
|
|
|
|
function stripAnsi(text) {
|
|
return text.replace(
|
|
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nq-uy=><]/g,
|
|
"",
|
|
);
|
|
}
|
|
|
|
function skipIfSpawnBlocked(result, t) {
|
|
if (result.error?.code === "EPERM") {
|
|
t.skip("spawnSync is blocked by sandbox policy in this environment");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
test("CLI renders expected output for a basic transcript", async (t) => {
|
|
const fixturePath = fileURLToPath(
|
|
new URL("./fixtures/transcript-render.jsonl", import.meta.url),
|
|
);
|
|
const expectedPath = fileURLToPath(
|
|
new URL("./fixtures/expected/render-basic.txt", import.meta.url),
|
|
);
|
|
const expected = readFileSync(expectedPath, "utf8").trimEnd();
|
|
|
|
const homeDir = await mkdtemp(path.join(tmpdir(), "claude-hud-home-"));
|
|
// Use a fixed 3-level path for deterministic test output
|
|
const projectDir = path.join(homeDir, "dev", "apps", "my-project");
|
|
await import("node:fs/promises").then((fs) =>
|
|
fs.mkdir(projectDir, { recursive: true }),
|
|
);
|
|
try {
|
|
const stdin = JSON.stringify({
|
|
model: { display_name: "Opus" },
|
|
context_window: {
|
|
context_window_size: 200000,
|
|
current_usage: { input_tokens: 45000 },
|
|
},
|
|
transcript_path: fixturePath,
|
|
cwd: projectDir,
|
|
});
|
|
|
|
const result = spawnSync("node", ["dist/index.js"], {
|
|
cwd: path.resolve(process.cwd()),
|
|
input: stdin,
|
|
encoding: "utf8",
|
|
env: { ...process.env, HOME: homeDir, LANG: "C" },
|
|
});
|
|
|
|
if (skipIfSpawnBlocked(result, t)) return;
|
|
|
|
assert.equal(result.error, undefined, result.error?.message);
|
|
assert.equal(result.status, 0, result.stderr || "non-zero exit");
|
|
const normalized = stripAnsi(result.stdout)
|
|
.replace(/\u00A0/g, " ")
|
|
.trimEnd();
|
|
if (process.env.UPDATE_SNAPSHOTS === "1") {
|
|
await writeFile(expectedPath, normalized + "\n", "utf8");
|
|
return;
|
|
}
|
|
assert.equal(normalized, expected);
|
|
} finally {
|
|
await rm(homeDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("CLI prints initializing message on empty stdin", (t) => {
|
|
const result = spawnSync("node", ["dist/index.js"], {
|
|
cwd: path.resolve(process.cwd()),
|
|
input: "",
|
|
encoding: "utf8",
|
|
env: { ...process.env, LANG: "C" },
|
|
});
|
|
|
|
if (skipIfSpawnBlocked(result, t)) return;
|
|
|
|
assert.equal(result.error, undefined, result.error?.message);
|
|
assert.equal(result.status, 0, result.stderr || "non-zero exit");
|
|
const normalized = stripAnsi(result.stdout)
|
|
.replace(/\u00A0/g, " ")
|
|
.trimEnd();
|
|
assert.ok(
|
|
normalized.startsWith("[claude-hud] Initializing..."),
|
|
`unexpected output: ${normalized}`,
|
|
);
|
|
});
|