118 lines
4.0 KiB
TypeScript
118 lines
4.0 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach, beforeAll, afterAll } from "vitest";
|
|
import { EventEmitter } from "node:events";
|
|
import { execSync } from "node:child_process";
|
|
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import type { Task } from "@fusion/core";
|
|
|
|
import { createApiRoutes } from "../routes.js";
|
|
|
|
class MockStore extends EventEmitter {
|
|
private tasks = new Map<string, Task>();
|
|
|
|
getRootDir(): string { return process.cwd(); }
|
|
async getTask(id: string): Promise<Task> {
|
|
const task = this.tasks.get(id);
|
|
if (!task) throw Object.assign(new Error("Task not found"), { code: "ENOENT" });
|
|
return task;
|
|
}
|
|
addTask(task: Task): void { this.tasks.set(task.id, task); }
|
|
getMissionStore() { return new EventEmitter(); }
|
|
async listTasks(): Promise<Task[]> { return []; }
|
|
}
|
|
|
|
function createTask(overrides: Partial<Task> = {}): Task {
|
|
return {
|
|
id: "FN-675", title: "Test task", description: "Test description",
|
|
column: "in-progress", dependencies: [], steps: [], currentStep: 0, log: [],
|
|
createdAt: "2026-04-01T00:00:00.000Z", updatedAt: "2026-04-01T00:00:00.000Z",
|
|
columnMovedAt: "2026-04-01T00:00:00.000Z", worktree: "/tmp/fn-675",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("Session files endpoint", () => {
|
|
let testWorktree: string;
|
|
let firstCommit: string;
|
|
|
|
beforeAll(() => {
|
|
// Create a test git repository
|
|
testWorktree = join(tmpdir(), `fn-test-${Date.now()}`);
|
|
mkdirSync(testWorktree, { recursive: true });
|
|
|
|
// Initialize git repo
|
|
execSync("git init --initial-branch=main", { cwd: testWorktree });
|
|
execSync("git config user.email test@test.com", { cwd: testWorktree });
|
|
execSync("git config user.name Test", { cwd: testWorktree });
|
|
|
|
// Create a commit
|
|
writeFileSync(join(testWorktree, "test.txt"), "initial content");
|
|
execSync("git add .", { cwd: testWorktree });
|
|
execSync("git commit -m 'initial'", { cwd: testWorktree });
|
|
|
|
// Get the first commit SHA
|
|
firstCommit = execSync("git rev-parse HEAD", { cwd: testWorktree }).toString().trim();
|
|
|
|
// Create a second commit with changes
|
|
writeFileSync(join(testWorktree, "changed.txt"), "new content");
|
|
execSync("git add .", { cwd: testWorktree });
|
|
execSync("git commit -m 'second commit'", { cwd: testWorktree });
|
|
|
|
console.log("Test worktree:", testWorktree);
|
|
console.log("First commit:", firstCommit);
|
|
});
|
|
|
|
afterAll(() => {
|
|
// Clean up
|
|
try {
|
|
rmSync(testWorktree, { recursive: true, force: true });
|
|
} catch (e) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers({ toFake: ["Date", "setTimeout", "clearTimeout", "setInterval", "clearInterval"] });
|
|
vi.setSystemTime(new Date("2026-04-01T12:00:00.000Z"));
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("endpoint should return files from git using real baseCommitSha", async () => {
|
|
const store = new MockStore();
|
|
|
|
store.addTask(createTask({
|
|
id: "FN-TEST", title: "Test", description: "Test",
|
|
column: "in-progress", dependencies: [], steps: [], currentStep: 0, log: [],
|
|
createdAt: "2026-04-01T00:00:00.000Z", updatedAt: "2026-04-01T00:00:00.000Z",
|
|
columnMovedAt: "2026-04-01T00:00:00.000Z", worktree: testWorktree, baseCommitSha: firstCommit,
|
|
}));
|
|
|
|
const router = createApiRoutes(store);
|
|
const layer = (router as any).stack.find(
|
|
(c: any) => c.route?.path === "/tasks/:id/session-files" && c.route?.methods?.get,
|
|
);
|
|
|
|
const handler = layer.route.stack[layer.route.stack.length - 1].handle;
|
|
|
|
const res: any = {
|
|
statusCode: 200,
|
|
body: undefined,
|
|
status(code: number) { this.statusCode = code; return this; },
|
|
json(payload: any) { this.body = payload; return this; }
|
|
};
|
|
|
|
await handler({ params: { id: "FN-TEST" } }, res);
|
|
|
|
console.log("Response body:", res.body);
|
|
|
|
expect(res.statusCode).toBe(200);
|
|
expect(Array.isArray(res.body)).toBe(true);
|
|
// Should have changed.txt as a changed file
|
|
expect(res.body).toContain("changed.txt");
|
|
});
|
|
});
|