/// import { CreditScoreService } from "../src/credit-score/credit-score.service"; import { createPrismaMock } from "./utils/mock-prisma"; describe("CreditScoreService", () => { const userId = "user_1"; let prisma: ReturnType; let notifications: { notifyUser: jest.Mock }; let service: CreditScoreService; beforeEach(() => { prisma = createPrismaMock(); notifications = { notifyUser: jest.fn().mockResolvedValue({}) }; service = new CreditScoreService(prisma as never, notifications as never); prisma.auditLog.create.mockResolvedValue({}); }); it("creates a score entry and sends an alert for a large drop", async () => { prisma.creditScoreEntry.findFirst.mockResolvedValue({ id: "old_1", userId, score: 760, bureau: "experian", scoreDate: new Date("2026-06-01T00:00:00.000Z"), }); prisma.creditScoreEntry.create.mockResolvedValue({ id: "score_1", userId, score: 730, bureau: "experian", source: "manual", model: "fico_8", scoreDate: new Date("2026-07-01T00:00:00.000Z"), factors: {}, metadata: {}, }); const result = await service.createEntry(userId, { score: 730, bureau: "experian", model: "fico_8", scoreDate: "2026-07-01", }); expect(result.change).toBe(-30); expect(prisma.auditLog.create).toHaveBeenCalledWith(expect.objectContaining({ data: expect.objectContaining({ action: "credit_score.entry_create" }), })); expect(notifications.notifyUser).toHaveBeenCalledWith(userId, expect.objectContaining({ type: "credit_score.change", severity: "warning", })); }); it("summarizes latest score, bureau snapshots, and trend", async () => { prisma.creditScoreEntry.findMany.mockResolvedValue([ { id: "s2", score: 720, bureau: "equifax", scoreDate: new Date("2026-07-05T00:00:00.000Z") }, { id: "s1", score: 700, bureau: "equifax", scoreDate: new Date("2026-06-05T00:00:00.000Z") }, { id: "s3", score: 740, bureau: "experian", scoreDate: new Date("2026-07-01T00:00:00.000Z") }, ]); const summary = await service.summary(userId); expect(summary.latest.id).toBe("s2"); expect(summary.change).toBe(20); expect(summary.averageScore).toBe(720); expect(summary.latestByBureau).toHaveLength(2); expect(summary.trend).toHaveLength(3); }); });