Files
arboretum/packages/server/test/claude-trust.test.ts
Johan LEROY acd920ebcd P3-A: worktrees multi-repo & cycle de vie (backend)
Enregistrement de repos et gestion de leurs worktrees git, source de vérité
= git (worktrees dérivés + cache court par repo), corrélation worktree ↔
sessions par cwd, mutations sérialisées par repo.

- shared: RepoSummary, PostCreateHook, WorktreeSummary, WorktreeGitStatus ;
  messages WS repo_update/worktree_update/*_removed ; topic sub 'worktrees'
  (+ parseClientMessage) ; DTOs REST repos/worktrees.
- db: migration id:3 (table repos).
- core/git.ts: couche git sûre (execFile, jamais de shell, -- avant chemins,
  GIT_OPTIONAL_LOCKS=0), parseWorktreePorcelain, list/add/remove/prune/status/
  ahead-behind, validation branche + chemin.
- core/claude-trust.ts: pré-trust atomique de ~/.claude.json (spike S3).
- core/worktree-manager.ts: repos CRUD, create (worktree add + pré-trust +
  hooks post-create + startSession optionnel), adopt, delete (garde-fous 409
  dirty / 400 main / 409 session live), prune ; events.
- routes/repos.ts + routes/worktrees.ts, câblage app.ts, gateway topic worktrees.
- tests: git (repos tmp réels), claude-trust, worktree-manager (146 verts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 18:31:06 +02:00

40 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, readFileSync, writeFileSync, rmSync, existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { preTrustProject } from '../src/core/claude-trust.js';
describe('preTrustProject', () => {
let dir: string;
let cfg: string;
beforeEach(() => {
dir = mkdtempSync(join(tmpdir(), 'arb-trust-'));
cfg = join(dir, '.claude.json');
});
afterEach(() => {
rmSync(dir, { recursive: true, force: true });
});
it('crée le fichier sil est absent et marque le worktree approuvé', () => {
expect(preTrustProject('/home/u/proj-wt-x', cfg)).toBe(true);
const data = JSON.parse(readFileSync(cfg, 'utf8'));
expect(data.projects['/home/u/proj-wt-x'].hasTrustDialogAccepted).toBe(true);
});
it('préserve la config existante (autres clés et projets)', () => {
writeFileSync(cfg, JSON.stringify({ theme: 'dark', projects: { '/other': { foo: 1 } } }));
expect(preTrustProject('/home/u/new', cfg)).toBe(true);
const data = JSON.parse(readFileSync(cfg, 'utf8'));
expect(data.theme).toBe('dark');
expect(data.projects['/other']).toEqual({ foo: 1 });
expect(data.projects['/home/u/new'].hasTrustDialogAccepted).toBe(true);
});
it('fichier corrompu → abandon SANS écraser (retourne false)', () => {
writeFileSync(cfg, '{ this is not json');
expect(preTrustProject('/home/u/x', cfg)).toBe(false);
expect(readFileSync(cfg, 'utf8')).toBe('{ this is not json'); // intact
expect(existsSync(`${cfg}.arb-tmp`)).toBe(false);
});
});