import { Test, TestingModule } from "@nestjs/testing"; import { MatrixRoomService } from "./matrix-room.service"; import { MatrixService } from "./matrix.service"; import { PrismaService } from "../../prisma/prisma.service"; import { vi, describe, it, expect, beforeEach } from "vitest"; // Mock matrix-bot-sdk to avoid native module import errors vi.mock("matrix-bot-sdk", () => { return { MatrixClient: class MockMatrixClient {}, SimpleFsStorageProvider: class MockStorageProvider { constructor(_filename: string) { // No-op for testing } }, AutojoinRoomsMixin: { setupOnClient: vi.fn(), }, }; }); describe("MatrixRoomService", () => { let service: MatrixRoomService; const mockCreateRoom = vi.fn().mockResolvedValue("!new-room:example.com"); const mockMatrixClient = { createRoom: mockCreateRoom, }; const mockMatrixService = { isConnected: vi.fn().mockReturnValue(true), getClient: vi.fn().mockReturnValue(mockMatrixClient), }; const mockPrismaService = { workspace: { findUnique: vi.fn(), findFirst: vi.fn(), update: vi.fn(), }, }; beforeEach(async () => { process.env.MATRIX_SERVER_NAME = "example.com"; const module: TestingModule = await Test.createTestingModule({ providers: [ MatrixRoomService, { provide: PrismaService, useValue: mockPrismaService, }, { provide: MatrixService, useValue: mockMatrixService, }, ], }).compile(); service = module.get(MatrixRoomService); vi.clearAllMocks(); // Restore defaults after clearing mockMatrixService.isConnected.mockReturnValue(true); mockCreateRoom.mockResolvedValue("!new-room:example.com"); mockPrismaService.workspace.update.mockResolvedValue({}); }); describe("provisionRoom", () => { it("should create a Matrix room and store the mapping", async () => { const roomId = await service.provisionRoom( "workspace-uuid-1", "My Workspace", "my-workspace" ); expect(roomId).toBe("!new-room:example.com"); expect(mockCreateRoom).toHaveBeenCalledWith({ name: "Mosaic: My Workspace", room_alias_name: "mosaic-my-workspace", topic: "Mosaic workspace: My Workspace", preset: "private_chat", visibility: "private", }); expect(mockPrismaService.workspace.update).toHaveBeenCalledWith({ where: { id: "workspace-uuid-1" }, data: { matrixRoomId: "!new-room:example.com" }, }); }); it("should return null when Matrix is not configured (no MatrixService)", async () => { // Create a service without MatrixService const module: TestingModule = await Test.createTestingModule({ providers: [ MatrixRoomService, { provide: PrismaService, useValue: mockPrismaService, }, ], }).compile(); const serviceWithoutMatrix = module.get(MatrixRoomService); const roomId = await serviceWithoutMatrix.provisionRoom( "workspace-uuid-1", "My Workspace", "my-workspace" ); expect(roomId).toBeNull(); expect(mockCreateRoom).not.toHaveBeenCalled(); expect(mockPrismaService.workspace.update).not.toHaveBeenCalled(); }); it("should return null when Matrix is not connected", async () => { mockMatrixService.isConnected.mockReturnValue(false); const roomId = await service.provisionRoom( "workspace-uuid-1", "My Workspace", "my-workspace" ); expect(roomId).toBeNull(); expect(mockCreateRoom).not.toHaveBeenCalled(); }); }); describe("getRoomForWorkspace", () => { it("should return the room ID for a mapped workspace", async () => { mockPrismaService.workspace.findUnique.mockResolvedValue({ matrixRoomId: "!mapped-room:example.com", }); const roomId = await service.getRoomForWorkspace("workspace-uuid-1"); expect(roomId).toBe("!mapped-room:example.com"); expect(mockPrismaService.workspace.findUnique).toHaveBeenCalledWith({ where: { id: "workspace-uuid-1" }, select: { matrixRoomId: true }, }); }); it("should return null for an unmapped workspace", async () => { mockPrismaService.workspace.findUnique.mockResolvedValue({ matrixRoomId: null, }); const roomId = await service.getRoomForWorkspace("workspace-uuid-2"); expect(roomId).toBeNull(); }); it("should return null for a non-existent workspace", async () => { mockPrismaService.workspace.findUnique.mockResolvedValue(null); const roomId = await service.getRoomForWorkspace("non-existent-uuid"); expect(roomId).toBeNull(); }); }); describe("getWorkspaceForRoom", () => { it("should return the workspace ID for a mapped room", async () => { mockPrismaService.workspace.findFirst.mockResolvedValue({ id: "workspace-uuid-1", }); const workspaceId = await service.getWorkspaceForRoom("!mapped-room:example.com"); expect(workspaceId).toBe("workspace-uuid-1"); expect(mockPrismaService.workspace.findFirst).toHaveBeenCalledWith({ where: { matrixRoomId: "!mapped-room:example.com" }, select: { id: true }, }); }); it("should return null for an unmapped room", async () => { mockPrismaService.workspace.findFirst.mockResolvedValue(null); const workspaceId = await service.getWorkspaceForRoom("!unknown-room:example.com"); expect(workspaceId).toBeNull(); }); }); describe("linkWorkspaceToRoom", () => { it("should store the room mapping in the workspace", async () => { await service.linkWorkspaceToRoom("workspace-uuid-1", "!existing-room:example.com"); expect(mockPrismaService.workspace.update).toHaveBeenCalledWith({ where: { id: "workspace-uuid-1" }, data: { matrixRoomId: "!existing-room:example.com" }, }); }); }); describe("unlinkWorkspace", () => { it("should remove the room mapping from the workspace", async () => { await service.unlinkWorkspace("workspace-uuid-1"); expect(mockPrismaService.workspace.update).toHaveBeenCalledWith({ where: { id: "workspace-uuid-1" }, data: { matrixRoomId: null }, }); }); }); });