/**
* Git Changes Strategy Tests
*/
import { describe, expect, it } from "bun:test";
import { GitChangesStrategy } from "@/staleness/strategies/git-changes";
import type { Memory } from "@/types";
const SECONDS_PER_DAY = 86400;
function createMockMemory(overrides: Partial<Memory> = {}): Memory {
const now = Math.floor(Date.now() / 1000);
return {
id: "test-memory-1",
type: "decision",
title: "Test Memory",
content: "Test content",
importance: 0.5,
tags: [],
relatedFiles: ["src/api.ts", "src/utils.ts"],
experts: [],
createdAt: now - 30 * SECONDS_PER_DAY,
accessedAt: now - 30 * SECONDS_PER_DAY,
accessCount: 1,
needsReview: false,
...overrides,
};
}
describe("GitChangesStrategy", () => {
const strategy = new GitChangesStrategy({
weight: 0.7,
cacheTtlMs: 5 * 60 * 1000,
});
it("should have correct type and weight", () => {
expect(strategy.type).toBe("git_changes");
expect(strategy.weight).toBe(0.7);
});
it("should return null for memories with no related files", async () => {
const now = Math.floor(Date.now() / 1000);
const memory = createMockMemory({
relatedFiles: [],
});
const signal = await strategy.check(memory, { now });
expect(signal).toBeNull();
});
it("should return null for memories with undefined related files", async () => {
const now = Math.floor(Date.now() / 1000);
const memory = createMockMemory();
// Remove relatedFiles
(memory as any).relatedFiles = undefined;
const signal = await strategy.check(memory, { now });
expect(signal).toBeNull();
});
it("should use lastRefreshedAt as anchor when available", async () => {
const now = Math.floor(Date.now() / 1000);
// This test verifies the anchor calculation logic
const memory = createMockMemory({
createdAt: now - 100 * SECONDS_PER_DAY,
accessedAt: now - 50 * SECONDS_PER_DAY,
lastRefreshedAt: now - 5 * SECONDS_PER_DAY,
});
// We can't easily mock git, but we can verify the strategy
// doesn't throw and handles the memory correctly
const _signal = await strategy.check(memory, { now });
// May return null or a signal depending on git state
// Just verify no errors
expect(true).toBe(true);
});
it("should initialize and dispose without errors", async () => {
const testStrategy = new GitChangesStrategy({
weight: 0.7,
cacheTtlMs: 1000,
});
await testStrategy.initialize();
await testStrategy.dispose();
// No errors means success
expect(true).toBe(true);
});
it("should include metadata when files have changed", async () => {
const now = Math.floor(Date.now() / 1000);
const memory = createMockMemory({
relatedFiles: ["package.json"], // A file that exists
});
// This will attempt to check git, which may or may not find changes
// The important thing is it doesn't error and returns proper structure
try {
const signal = await strategy.check(memory, { now });
if (signal) {
expect(signal.strategy).toBe("git_changes");
expect(signal.weight).toBe(0.7);
expect(signal.metadata).toBeDefined();
}
} catch {
// Git may not be available in test environment
expect(true).toBe(true);
}
});
});