import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { CronService } from "./cron.service"; import { PrismaService } from "../prisma/prisma.service"; describe("CronService", () => { let service: CronService; let prisma: PrismaService; const mockPrisma = { cronSchedule: { create: vi.fn(), findMany: vi.fn(), findUnique: vi.fn(), update: vi.fn(), delete: vi.fn(), }, }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ CronService, { provide: PrismaService, useValue: mockPrisma, }, ], }).compile(); service = module.get(CronService); prisma = module.get(PrismaService); vi.clearAllMocks(); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("create", () => { it("should create a cron schedule", async () => { const createDto = { workspaceId: "ws-123", expression: "0 9 * * *", command: "morning briefing", }; const expectedSchedule = { id: "cron-1", ...createDto, enabled: true, createdAt: new Date(), updatedAt: new Date(), }; mockPrisma.cronSchedule.create.mockResolvedValue(expectedSchedule); const result = await service.create(createDto); expect(result).toEqual(expectedSchedule); expect(mockPrisma.cronSchedule.create).toHaveBeenCalledWith({ data: { workspaceId: createDto.workspaceId, expression: createDto.expression, command: createDto.command, enabled: true, }, }); }); it("should reject invalid cron expressions", async () => { const createDto = { workspaceId: "ws-123", expression: "not-a-cron", command: "test command", }; await expect(service.create(createDto)).rejects.toThrow("Invalid cron expression"); }); }); describe("findAll", () => { it("should return all schedules for a workspace", async () => { const workspaceId = "ws-123"; const expectedSchedules = [ { id: "cron-1", workspaceId, expression: "0 9 * * *", command: "morning briefing", enabled: true, }, { id: "cron-2", workspaceId, expression: "0 17 * * *", command: "evening summary", enabled: true, }, ]; mockPrisma.cronSchedule.findMany.mockResolvedValue(expectedSchedules); const result = await service.findAll(workspaceId); expect(result).toEqual(expectedSchedules); expect(mockPrisma.cronSchedule.findMany).toHaveBeenCalledWith({ where: { workspaceId }, orderBy: { createdAt: "desc" }, }); }); }); describe("findOne", () => { it("should return a schedule by id", async () => { const schedule = { id: "cron-1", workspaceId: "ws-123", expression: "0 9 * * *", command: "morning briefing", enabled: true, }; mockPrisma.cronSchedule.findUnique.mockResolvedValue(schedule); const result = await service.findOne("cron-1", "ws-123"); expect(result).toEqual(schedule); expect(mockPrisma.cronSchedule.findUnique).toHaveBeenCalledWith({ where: { id: "cron-1" }, }); }); it("should return null if schedule not found", async () => { mockPrisma.cronSchedule.findUnique.mockResolvedValue(null); const result = await service.findOne("cron-999", "ws-123"); expect(result).toBeNull(); }); }); describe("update", () => { it("should update a cron schedule", async () => { const updateDto = { expression: "0 8 * * *", enabled: false }; const expectedSchedule = { id: "cron-1", workspaceId: "ws-123", expression: "0 8 * * *", command: "morning briefing", enabled: false, }; mockPrisma.cronSchedule.findUnique.mockResolvedValue({ id: "cron-1", workspaceId: "ws-123" }); mockPrisma.cronSchedule.update.mockResolvedValue(expectedSchedule); const result = await service.update("cron-1", "ws-123", updateDto); expect(result).toEqual(expectedSchedule); expect(mockPrisma.cronSchedule.update).toHaveBeenCalled(); }); }); describe("remove", () => { it("should delete a cron schedule", async () => { const schedule = { id: "cron-1", workspaceId: "ws-123", expression: "0 9 * * *", command: "morning briefing", enabled: true, }; mockPrisma.cronSchedule.findUnique.mockResolvedValue(schedule); mockPrisma.cronSchedule.delete.mockResolvedValue(schedule); const result = await service.remove("cron-1", "ws-123"); expect(result).toEqual(schedule); expect(mockPrisma.cronSchedule.delete).toHaveBeenCalledWith({ where: { id: "cron-1" }, }); }); it("should throw if schedule belongs to different workspace", async () => { mockPrisma.cronSchedule.findUnique.mockResolvedValue({ id: "cron-1", workspaceId: "ws-456", }); await expect(service.remove("cron-1", "ws-123")).rejects.toThrow( "Not authorized to delete this schedule" ); }); }); });