/** * Query Controller Tests * * Tests for federated query API endpoints. */ import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { FederationMessageType, FederationMessageStatus } from "@prisma/client"; import { QueryController } from "./query.controller"; import { QueryService } from "./query.service"; import { AuthGuard } from "../auth/guards/auth.guard"; import type { AuthenticatedRequest } from "../common/types/user.types"; import type { SendQueryDto, IncomingQueryDto } from "./dto/query.dto"; describe("QueryController", () => { let controller: QueryController; let queryService: QueryService; const mockQueryService = { sendQuery: vi.fn(), handleIncomingQuery: vi.fn(), getQueryMessages: vi.fn(), getQueryMessage: vi.fn(), }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [QueryController], providers: [{ provide: QueryService, useValue: mockQueryService }], }) .overrideGuard(AuthGuard) .useValue({ canActivate: () => true }) .compile(); controller = module.get(QueryController); queryService = module.get(QueryService); vi.clearAllMocks(); }); describe("sendQuery", () => { it("should send query to remote instance", async () => { const req = { user: { id: "user-1", workspaceId: "workspace-1", }, } as AuthenticatedRequest; const dto: SendQueryDto = { connectionId: "connection-1", query: "SELECT * FROM tasks", context: { userId: "user-1" }, }; const mockResult = { id: "msg-1", workspaceId: "workspace-1", connectionId: "connection-1", messageType: FederationMessageType.QUERY, messageId: "unique-msg-1", query: dto.query, status: FederationMessageStatus.PENDING, createdAt: new Date(), updatedAt: new Date(), }; mockQueryService.sendQuery.mockResolvedValue(mockResult); const result = await controller.sendQuery(req, dto); expect(result).toBeDefined(); expect(result.messageType).toBe(FederationMessageType.QUERY); expect(mockQueryService.sendQuery).toHaveBeenCalledWith( "workspace-1", dto.connectionId, dto.query, dto.context ); }); it("should throw error if user not authenticated", async () => { const req = {} as AuthenticatedRequest; const dto: SendQueryDto = { connectionId: "connection-1", query: "SELECT * FROM tasks", }; await expect(controller.sendQuery(req, dto)).rejects.toThrow( "Workspace ID not found in request" ); }); }); describe("handleIncomingQuery", () => { it("should process incoming query", async () => { const dto: IncomingQueryDto = { messageId: "msg-1", instanceId: "remote-instance-1", query: "SELECT * FROM tasks", timestamp: Date.now(), signature: "valid-signature", }; const mockResponse = { messageId: "response-1", correlationId: dto.messageId, instanceId: "local-instance-1", success: true, data: { tasks: [] }, timestamp: Date.now(), signature: "response-signature", }; mockQueryService.handleIncomingQuery.mockResolvedValue(mockResponse); const result = await controller.handleIncomingQuery(dto); expect(result).toBeDefined(); expect(result.correlationId).toBe(dto.messageId); expect(mockQueryService.handleIncomingQuery).toHaveBeenCalledWith(dto); }); it("should return error response for invalid query", async () => { const dto: IncomingQueryDto = { messageId: "msg-1", instanceId: "remote-instance-1", query: "SELECT * FROM tasks", timestamp: Date.now(), signature: "invalid-signature", }; mockQueryService.handleIncomingQuery.mockRejectedValue(new Error("Invalid signature")); await expect(controller.handleIncomingQuery(dto)).rejects.toThrow("Invalid signature"); }); }); describe("getQueries", () => { it("should return query messages for workspace", async () => { const req = { user: { id: "user-1", workspaceId: "workspace-1", }, } as AuthenticatedRequest; const mockMessages = [ { id: "msg-1", workspaceId: "workspace-1", connectionId: "connection-1", messageType: FederationMessageType.QUERY, messageId: "unique-msg-1", query: "SELECT * FROM tasks", status: FederationMessageStatus.DELIVERED, createdAt: new Date(), updatedAt: new Date(), }, ]; mockQueryService.getQueryMessages.mockResolvedValue(mockMessages); const result = await controller.getQueries(req, undefined); expect(result).toHaveLength(1); expect(mockQueryService.getQueryMessages).toHaveBeenCalledWith("workspace-1", undefined); }); it("should filter by status when provided", async () => { const req = { user: { id: "user-1", workspaceId: "workspace-1", }, } as AuthenticatedRequest; const status = FederationMessageStatus.PENDING; mockQueryService.getQueryMessages.mockResolvedValue([]); await controller.getQueries(req, status); expect(mockQueryService.getQueryMessages).toHaveBeenCalledWith("workspace-1", status); }); it("should throw error if user not authenticated", async () => { const req = {} as AuthenticatedRequest; await expect(controller.getQueries(req, undefined)).rejects.toThrow( "Workspace ID not found in request" ); }); }); describe("getQuery", () => { it("should return query message by ID", async () => { const req = { user: { id: "user-1", workspaceId: "workspace-1", }, } as AuthenticatedRequest; const messageId = "msg-1"; const mockMessage = { id: messageId, workspaceId: "workspace-1", connectionId: "connection-1", messageType: FederationMessageType.QUERY, messageId: "unique-msg-1", query: "SELECT * FROM tasks", status: FederationMessageStatus.DELIVERED, createdAt: new Date(), updatedAt: new Date(), }; mockQueryService.getQueryMessage.mockResolvedValue(mockMessage); const result = await controller.getQuery(req, messageId); expect(result).toBeDefined(); expect(result.id).toBe(messageId); expect(mockQueryService.getQueryMessage).toHaveBeenCalledWith("workspace-1", messageId); }); it("should throw error if user not authenticated", async () => { const req = {} as AuthenticatedRequest; await expect(controller.getQuery(req, "msg-1")).rejects.toThrow( "Workspace ID not found in request" ); }); }); });