import { describe, it, expect, beforeEach, vi } from "vitest"; // Mock WebSocketGateway before importing the service vi.mock("../websocket/websocket.gateway", () => ({ WebSocketGateway: vi.fn().mockImplementation(() => ({ emitCronExecuted: vi.fn(), })), })); // Mock PrismaService const mockPrisma = { cronSchedule: { findMany: vi.fn(), findUnique: vi.fn(), update: vi.fn(), }, }; vi.mock("../prisma/prisma.service", () => ({ PrismaService: vi.fn().mockImplementation(() => mockPrisma), })); // Now import the service import { CronSchedulerService } from "./cron.scheduler"; describe("CronSchedulerService", () => { let service: CronSchedulerService; beforeEach(async () => { vi.clearAllMocks(); // Create service with mocked dependencies service = new CronSchedulerService(mockPrisma as any, { emitCronExecuted: vi.fn() } as any); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("getStatus", () => { it("should return running status", () => { const status = service.getStatus(); expect(status).toHaveProperty("running"); expect(status).toHaveProperty("checkIntervalMs"); }); }); describe("processDueSchedules", () => { it("should find due schedules with null nextRun", async () => { mockPrisma.cronSchedule.findMany.mockResolvedValue([]); await service.processDueSchedules(); // Verify the call was made with correct structure const call = mockPrisma.cronSchedule.findMany.mock.calls[0]?.[0]; expect(call).toBeDefined(); expect(call?.where?.enabled).toBe(true); expect(call?.where?.OR).toHaveLength(2); expect(call?.where?.OR?.[0]).toEqual({ nextRun: null }); expect(call?.where?.OR?.[1]?.nextRun?.lte).toBeInstanceOf(Date); }); it("should return empty array when no schedules are due", async () => { mockPrisma.cronSchedule.findMany.mockResolvedValue([]); const result = await service.processDueSchedules(); expect(result).toEqual([]); }); it("should handle errors gracefully", async () => { mockPrisma.cronSchedule.findMany.mockRejectedValue(new Error("DB error")); const result = await service.processDueSchedules(); expect(result).toEqual([]); }); }); describe("triggerManual", () => { it("should return null for non-existent schedule", async () => { mockPrisma.cronSchedule.findUnique.mockResolvedValue(null); const result = await service.triggerManual("cron-999"); expect(result).toBeNull(); }); it("should return null for disabled schedule", async () => { mockPrisma.cronSchedule.findUnique.mockResolvedValue({ id: "cron-1", enabled: false, command: "test", workspaceId: "ws-123", }); const result = await service.triggerManual("cron-1"); expect(result).toBeNull(); }); }); describe("startScheduler / stopScheduler", () => { it("should start and stop the scheduler", () => { expect(service.getStatus().running).toBe(false); service.startScheduler(); expect(service.getStatus().running).toBe(true); service.stopScheduler(); expect(service.getStatus().running).toBe(false); }); it("should not start multiple schedulers", () => { service.startScheduler(); const firstInterval = service.getStatus().checkIntervalMs; service.startScheduler(); expect(service.getStatus().checkIntervalMs).toBe(firstInterval); service.stopScheduler(); }); }); });