88 lines
3 KiB
TypeScript
88 lines
3 KiB
TypeScript
import fs from 'fs';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
|
|
import { RuntimeTurnSettledSpoolPaths } from '@features/member-work-sync/main/infrastructure/RuntimeTurnSettledSpoolPaths';
|
|
import { ShellRuntimeTurnSettledHookScriptInstaller } from '@features/member-work-sync/main/infrastructure/ShellRuntimeTurnSettledHookScriptInstaller';
|
|
import {
|
|
MEMBER_WORK_SYNC_TURN_SETTLED_HOOK_MARKER,
|
|
buildRuntimeTurnSettledHookCommand,
|
|
buildRuntimeTurnSettledHookSettings,
|
|
} from '@features/member-work-sync/main/infrastructure/runtimeTurnSettledHookSettings';
|
|
|
|
const tempRoots: string[] = [];
|
|
|
|
function makeTempRoot(): string {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'runtime-turn-settled-hook-'));
|
|
tempRoots.push(root);
|
|
return root;
|
|
}
|
|
|
|
afterEach(() => {
|
|
for (const root of tempRoots.splice(0)) {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
describe('runtime turn-settled hook settings', () => {
|
|
it('builds a shell-quoted command without embedding team identity', () => {
|
|
const command = buildRuntimeTurnSettledHookCommand({
|
|
scriptPath: "/tmp/agent team's hook.sh",
|
|
spoolRoot: '/tmp/member work sync',
|
|
provider: 'claude',
|
|
});
|
|
|
|
expect(command).toContain('/bin/sh');
|
|
expect(command).toContain("'/tmp/agent team'\\''s hook.sh'");
|
|
expect(command).toContain("'claude'");
|
|
expect(command).toContain(MEMBER_WORK_SYNC_TURN_SETTLED_HOOK_MARKER);
|
|
expect(command).not.toContain('--team-name');
|
|
expect(command).not.toContain('--agent-name');
|
|
});
|
|
|
|
it('builds Claude Stop hook settings with a stable marker', () => {
|
|
const settings = buildRuntimeTurnSettledHookSettings({
|
|
scriptPath: '/tmp/hook.sh',
|
|
spoolRoot: '/tmp/spool',
|
|
provider: 'claude',
|
|
});
|
|
|
|
expect(settings).toEqual({
|
|
hooks: {
|
|
Stop: [
|
|
{
|
|
matcher: '',
|
|
hooks: [
|
|
{
|
|
type: 'command',
|
|
command: expect.stringContaining(MEMBER_WORK_SYNC_TURN_SETTLED_HOOK_MARKER),
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
});
|
|
});
|
|
|
|
it('installs an executable POSIX shell writer and spool directories', async () => {
|
|
const root = makeTempRoot();
|
|
const paths = new RuntimeTurnSettledSpoolPaths(root);
|
|
const installer = new ShellRuntimeTurnSettledHookScriptInstaller(paths);
|
|
|
|
const result = await installer.install();
|
|
|
|
expect(result.scriptPath).toBe(paths.getHookScriptPath());
|
|
expect(result.spoolRoot).toBe(paths.getRootDir());
|
|
expect(fs.existsSync(paths.getIncomingDir())).toBe(true);
|
|
expect(fs.existsSync(paths.getProcessingDir())).toBe(true);
|
|
expect(fs.existsSync(paths.getProcessedDir())).toBe(true);
|
|
expect(fs.existsSync(paths.getInvalidDir())).toBe(true);
|
|
|
|
if (process.platform !== 'win32') {
|
|
const stat = fs.statSync(result.scriptPath);
|
|
expect(stat.mode & 0o111).toBeGreaterThan(0);
|
|
}
|
|
expect(fs.readFileSync(result.scriptPath, 'utf8')).toContain('dd bs="$max_bytes"');
|
|
});
|
|
});
|