Files
socraticode/tests/integration/watcher.test.ts
T
2026-02-28 17:06:21 +00:00

108 lines
3.2 KiB
TypeScript

// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Giancarlo Erra - Altaire Limited
import path from "node:path";
import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest";
import { ensureQdrantReady } from "../../src/services/docker.js";
import { indexProject } from "../../src/services/indexer.js";
import { ensureOllamaReady } from "../../src/services/ollama.js";
import {
getWatchedProjects,
isWatching,
startWatching,
stopAllWatchers,
stopWatching,
} from "../../src/services/watcher.js";
import {
createFixtureProject,
type FixtureProject,
isDockerAvailable,
} from "../helpers/fixtures.js";
import { cleanupTestCollections, waitForOllama, waitForQdrant } from "../helpers/setup.js";
const dockerAvailable = isDockerAvailable();
describe.skipIf(!dockerAvailable)("watcher service", () => {
let fixture: FixtureProject;
beforeAll(async () => {
await ensureQdrantReady();
await ensureOllamaReady();
await waitForQdrant();
await waitForOllama();
fixture = createFixtureProject("watcher-test");
// Index the project first so the watcher has a collection to update
await indexProject(fixture.root);
}, 180_000);
afterAll(async () => {
await stopAllWatchers();
fixture.cleanup();
await cleanupTestCollections(fixture.root);
});
afterEach(async () => {
// Stop watchers between tests
if (isWatching(fixture.root)) {
await stopWatching(fixture.root);
}
});
describe("startWatching / stopWatching", () => {
it("starts watching a project", async () => {
await startWatching(fixture.root);
expect(isWatching(fixture.root)).toBe(true);
});
it("includes the project in watched list", async () => {
await startWatching(fixture.root);
const watched = getWatchedProjects();
expect(watched).toContain(path.resolve(fixture.root));
});
it("stops watching a project", async () => {
await startWatching(fixture.root);
expect(isWatching(fixture.root)).toBe(true);
await stopWatching(fixture.root);
expect(isWatching(fixture.root)).toBe(false);
});
it("does not error when stopping a non-watched project", async () => {
await expect(stopWatching("/nonexistent/path")).resolves.not.toThrow();
});
it("is idempotent — starting twice does not error", async () => {
await startWatching(fixture.root);
await startWatching(fixture.root);
expect(isWatching(fixture.root)).toBe(true);
});
});
describe("stopAllWatchers", () => {
it("stops all active watchers", async () => {
await startWatching(fixture.root);
expect(getWatchedProjects().length).toBeGreaterThan(0);
await stopAllWatchers();
expect(getWatchedProjects()).toHaveLength(0);
});
});
describe("getWatchedProjects", () => {
it("returns empty list when nothing is watched", async () => {
await stopAllWatchers();
expect(getWatchedProjects()).toHaveLength(0);
});
it("returns all watched projects", async () => {
await startWatching(fixture.root);
const projects = getWatchedProjects();
expect(projects.length).toBe(1);
expect(projects[0]).toBe(path.resolve(fixture.root));
});
});
});