import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { StatsService } from "./stats.service"; import { PrismaService } from "../../prisma/prisma.service"; import { EntryStatus } from "@prisma/client"; describe("StatsService", () => { let service: StatsService; let prisma: PrismaService; const mockPrismaService = { knowledgeEntry: { count: vi.fn(), findMany: vi.fn(), }, knowledgeTag: { count: vi.fn(), findMany: vi.fn(), }, knowledgeLink: { count: vi.fn(), }, }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ StatsService, { provide: PrismaService, useValue: mockPrismaService, }, ], }).compile(); service = module.get(StatsService); prisma = module.get(PrismaService); vi.clearAllMocks(); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("getStats", () => { it("should return knowledge base statistics", async () => { // Mock all the parallel queries mockPrismaService.knowledgeEntry.count .mockResolvedValueOnce(10) // total entries .mockResolvedValueOnce(5) // published .mockResolvedValueOnce(3) // drafts .mockResolvedValueOnce(2); // archived mockPrismaService.knowledgeTag.count.mockResolvedValue(7); mockPrismaService.knowledgeLink.count.mockResolvedValue(15); mockPrismaService.knowledgeEntry.findMany .mockResolvedValueOnce([ // most connected { id: "entry-1", slug: "test-entry", title: "Test Entry", _count: { incomingLinks: 5, outgoingLinks: 3 }, }, ]) .mockResolvedValueOnce([ // recent activity { id: "entry-2", slug: "recent-entry", title: "Recent Entry", updatedAt: new Date(), status: EntryStatus.PUBLISHED, }, ]); mockPrismaService.knowledgeTag.findMany.mockResolvedValue([ { id: "tag-1", name: "Test Tag", slug: "test-tag", color: "#FF0000", _count: { entries: 3 }, }, ]); const result = await service.getStats("workspace-1"); expect(result.overview.totalEntries).toBe(10); expect(result.overview.totalTags).toBe(7); expect(result.overview.totalLinks).toBe(15); expect(result.overview.publishedEntries).toBe(5); expect(result.overview.draftEntries).toBe(3); expect(result.overview.archivedEntries).toBe(2); expect(result.mostConnected).toHaveLength(1); expect(result.mostConnected[0].totalConnections).toBe(8); expect(result.recentActivity).toHaveLength(1); expect(result.tagDistribution).toHaveLength(1); }); it("should handle empty knowledge base", async () => { // Mock all counts as 0 mockPrismaService.knowledgeEntry.count.mockResolvedValue(0); mockPrismaService.knowledgeTag.count.mockResolvedValue(0); mockPrismaService.knowledgeLink.count.mockResolvedValue(0); mockPrismaService.knowledgeEntry.findMany.mockResolvedValue([]); mockPrismaService.knowledgeTag.findMany.mockResolvedValue([]); const result = await service.getStats("workspace-1"); expect(result.overview.totalEntries).toBe(0); expect(result.overview.totalTags).toBe(0); expect(result.overview.totalLinks).toBe(0); expect(result.mostConnected).toHaveLength(0); expect(result.recentActivity).toHaveLength(0); expect(result.tagDistribution).toHaveLength(0); }); }); });