99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
// tests/mutator/claude.test.ts — Test Claude settings hook injection
|
|
|
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
import fs from "fs";
|
|
import os from "os";
|
|
import path from "path";
|
|
|
|
import { SCRIPT_NAME } from "../../src/utils/config";
|
|
|
|
describe("Claude settings hook format", () => {
|
|
const testDir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-test-"));
|
|
const settingsPath = path.join(testDir, ".claude", "settings.json");
|
|
|
|
beforeEach(() => {
|
|
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
});
|
|
|
|
test("creates nested hook structure from empty settings", () => {
|
|
const hookCommand = "bun run ~/.claude/package/opensearch_init.js";
|
|
|
|
// Start with empty settings
|
|
fs.writeFileSync(settingsPath, "{}", "utf-8");
|
|
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
settings.hooks = {};
|
|
settings.hooks.SessionStart = [];
|
|
settings.hooks.SessionStart.push({
|
|
matcher: "*",
|
|
hooks: [{ type: "command", command: hookCommand }],
|
|
});
|
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
|
|
const result = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
expect(result.hooks).toBeDefined();
|
|
expect(result.hooks.SessionStart).toBeInstanceOf(Array);
|
|
expect(result.hooks.SessionStart[0]).toEqual({
|
|
matcher: "*",
|
|
hooks: [{ type: "command", command: hookCommand }],
|
|
});
|
|
});
|
|
|
|
test("appends to existing nested hook", () => {
|
|
const hookCommand1 = "bun run ~/.claude/package/opensearch_init.js";
|
|
const hookCommand2 = "bun run ~/.codex/package/opensearch_init.js";
|
|
|
|
const existing = {
|
|
hooks: {
|
|
SessionStart: [
|
|
{
|
|
matcher: "*",
|
|
hooks: [
|
|
{ type: "command", command: ".vscode/setup.mjs" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
fs.writeFileSync(settingsPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
|
|
// Simulate adding two hooks
|
|
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
const entry = settings.hooks.SessionStart[0];
|
|
entry.hooks.push({ type: "command", command: hookCommand1 });
|
|
entry.hooks.push({ type: "command", command: hookCommand2 });
|
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
|
|
const result = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
expect(result.hooks.SessionStart[0].hooks.length).toBe(3);
|
|
expect(result.hooks.SessionStart[0].hooks[1]).toEqual({
|
|
type: "command",
|
|
command: hookCommand1,
|
|
});
|
|
expect(result.hooks.SessionStart[0].hooks[2]).toEqual({
|
|
type: "command",
|
|
command: hookCommand2,
|
|
});
|
|
});
|
|
|
|
test("creates matcher entry when SessionStart is empty array", () => {
|
|
const hookCommand = "bun run ~/.codex/package/opensearch_init.js";
|
|
fs.writeFileSync(settingsPath, "{}", "utf-8");
|
|
|
|
const settings = { hooks: { SessionStart: [] as any[] } };
|
|
settings.hooks.SessionStart.push({
|
|
matcher: "*",
|
|
hooks: [{ type: "command", command: hookCommand }],
|
|
});
|
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
|
|
const result = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
expect(result.hooks.SessionStart[0]).toEqual({
|
|
matcher: "*",
|
|
hooks: [{ type: "command", command: hookCommand }],
|
|
});
|
|
});
|
|
}); |