/** * TerminalSessionService Tests * * Unit tests for database-backed terminal session CRUD: * create, findByWorkspace, close, and findById. * PrismaService is mocked to isolate the service logic. */ import { describe, it, expect, beforeEach, vi } from "vitest"; import { NotFoundException } from "@nestjs/common"; import { TerminalSessionStatus } from "@prisma/client"; import type { TerminalSession } from "@prisma/client"; import { TerminalSessionService } from "./terminal-session.service"; // ========================================== // Helpers // ========================================== function makeSession(overrides: Partial = {}): TerminalSession { return { id: "session-uuid-1", workspaceId: "workspace-uuid-1", name: "Terminal", status: TerminalSessionStatus.ACTIVE, createdAt: new Date("2026-02-25T00:00:00Z"), closedAt: null, ...overrides, }; } // ========================================== // Mock PrismaService // ========================================== function makeMockPrisma() { return { terminalSession: { create: vi.fn(), findMany: vi.fn(), findUnique: vi.fn(), update: vi.fn(), }, }; } // ========================================== // Tests // ========================================== describe("TerminalSessionService", () => { let service: TerminalSessionService; // eslint-disable-next-line @typescript-eslint/no-explicit-any let mockPrisma: any; beforeEach(() => { vi.clearAllMocks(); mockPrisma = makeMockPrisma(); service = new TerminalSessionService(mockPrisma); }); // ========================================== // create // ========================================== describe("create", () => { it("should call prisma.terminalSession.create with workspaceId only when no name provided", async () => { const session = makeSession(); mockPrisma.terminalSession.create.mockResolvedValueOnce(session); const result = await service.create("workspace-uuid-1"); expect(mockPrisma.terminalSession.create).toHaveBeenCalledWith({ data: { workspaceId: "workspace-uuid-1" }, }); expect(result).toEqual(session); }); it("should include name in create data when name is provided", async () => { const session = makeSession({ name: "My Terminal" }); mockPrisma.terminalSession.create.mockResolvedValueOnce(session); const result = await service.create("workspace-uuid-1", "My Terminal"); expect(mockPrisma.terminalSession.create).toHaveBeenCalledWith({ data: { workspaceId: "workspace-uuid-1", name: "My Terminal" }, }); expect(result).toEqual(session); }); it("should return the created session", async () => { const session = makeSession(); mockPrisma.terminalSession.create.mockResolvedValueOnce(session); const result = await service.create("workspace-uuid-1"); expect(result.id).toBe("session-uuid-1"); expect(result.status).toBe(TerminalSessionStatus.ACTIVE); }); }); // ========================================== // findByWorkspace // ========================================== describe("findByWorkspace", () => { it("should query for ACTIVE sessions in the given workspace, ordered by createdAt desc", async () => { const sessions = [makeSession(), makeSession({ id: "session-uuid-2" })]; mockPrisma.terminalSession.findMany.mockResolvedValueOnce(sessions); const result = await service.findByWorkspace("workspace-uuid-1"); expect(mockPrisma.terminalSession.findMany).toHaveBeenCalledWith({ where: { workspaceId: "workspace-uuid-1", status: TerminalSessionStatus.ACTIVE, }, orderBy: { createdAt: "desc" }, }); expect(result).toHaveLength(2); }); it("should return an empty array when no active sessions exist", async () => { mockPrisma.terminalSession.findMany.mockResolvedValueOnce([]); const result = await service.findByWorkspace("workspace-uuid-empty"); expect(result).toEqual([]); }); it("should not include CLOSED sessions", async () => { // The where clause enforces ACTIVE status — verify it is present mockPrisma.terminalSession.findMany.mockResolvedValueOnce([]); await service.findByWorkspace("workspace-uuid-1"); const callArgs = mockPrisma.terminalSession.findMany.mock.calls[0][0] as { where: { status: TerminalSessionStatus }; }; expect(callArgs.where.status).toBe(TerminalSessionStatus.ACTIVE); }); }); // ========================================== // close // ========================================== describe("close", () => { it("should set status to CLOSED and set closedAt when session exists", async () => { const existingSession = makeSession(); const closedSession = makeSession({ status: TerminalSessionStatus.CLOSED, closedAt: new Date("2026-02-25T01:00:00Z"), }); mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(existingSession); mockPrisma.terminalSession.update.mockResolvedValueOnce(closedSession); const result = await service.close("session-uuid-1"); expect(mockPrisma.terminalSession.findUnique).toHaveBeenCalledWith({ where: { id: "session-uuid-1" }, }); expect(mockPrisma.terminalSession.update).toHaveBeenCalledWith({ where: { id: "session-uuid-1" }, data: { status: TerminalSessionStatus.CLOSED, closedAt: expect.any(Date), }, }); expect(result.status).toBe(TerminalSessionStatus.CLOSED); }); it("should throw NotFoundException when session does not exist", async () => { mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(null); await expect(service.close("nonexistent-id")).rejects.toThrow(NotFoundException); expect(mockPrisma.terminalSession.update).not.toHaveBeenCalled(); }); it("should include a non-null closedAt timestamp on close", async () => { const existingSession = makeSession(); const closedSession = makeSession({ status: TerminalSessionStatus.CLOSED, closedAt: new Date(), }); mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(existingSession); mockPrisma.terminalSession.update.mockResolvedValueOnce(closedSession); const result = await service.close("session-uuid-1"); expect(result.closedAt).not.toBeNull(); }); }); // ========================================== // findById // ========================================== describe("findById", () => { it("should return the session when it exists", async () => { const session = makeSession(); mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(session); const result = await service.findById("session-uuid-1"); expect(mockPrisma.terminalSession.findUnique).toHaveBeenCalledWith({ where: { id: "session-uuid-1" }, }); expect(result).toEqual(session); }); it("should return null when session does not exist", async () => { mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(null); const result = await service.findById("no-such-id"); expect(result).toBeNull(); }); it("should find CLOSED sessions as well as ACTIVE ones", async () => { const closedSession = makeSession({ status: TerminalSessionStatus.CLOSED, closedAt: new Date(), }); mockPrisma.terminalSession.findUnique.mockResolvedValueOnce(closedSession); const result = await service.findById("session-uuid-1"); expect(result?.status).toBe(TerminalSessionStatus.CLOSED); }); }); });