/** * Testes para EvolutionAPI Client * * NOTA: Estes testes requerem Vitest configurado. * Para instalar: npm install -D vitest @vitest/ui * Para executar: npm run test * * TODO: Adicionar script "test": "vitest" no package.json */ import { beforeEach, describe, expect, it, vi } from "vitest"; import { disconnectInstance, generateQRCode, getAllInstancesStatus, getInstanceNames, getInstanceStatus, } from "../evolutionapi"; // Mock global fetch global.fetch = vi.fn(); describe("EvolutionAPI Client", () => { beforeEach(() => { vi.clearAllMocks(); // Reset env vars process.env.EVOLUTION_API_URL = "https://api.test.com"; process.env.EVOLUTION_API_KEY = "test-api-key"; process.env.EVOLUTION_INSTANCE_NAMES = "instance1,instance2,instance3"; }); describe("getInstanceNames", () => { it("should parse comma-separated instance names", () => { const instances = getInstanceNames(); expect(instances).toEqual(["instance1", "instance2", "instance3"]); }); it("should handle empty string", () => { process.env.EVOLUTION_INSTANCE_NAMES = ""; const instances = getInstanceNames(); expect(instances).toEqual([]); }); it("should trim whitespace", () => { process.env.EVOLUTION_INSTANCE_NAMES = " instance1 , instance2 , instance3 "; const instances = getInstanceNames(); expect(instances).toEqual(["instance1", "instance2", "instance3"]); }); }); describe("getInstanceStatus", () => { it("should return connected status when state is open", async () => { const mockResponse = { instance: { instanceName: "test-instance", state: "open", }, }; (global.fetch as any).mockResolvedValueOnce({ ok: true, status: 200, json: async () => mockResponse, }); const result = await getInstanceStatus("test-instance"); expect(result).toEqual({ instance: "test-instance", status: "connected", }); expect(global.fetch).toHaveBeenCalledWith( "https://api.test.com/instance/connectionState/test-instance", expect.objectContaining({ method: "GET", headers: expect.objectContaining({ apikey: "test-api-key", }), }), ); }); it("should return disconnected status when state is not open", async () => { const mockResponse = { instance: { instanceName: "test-instance", state: "close", }, }; (global.fetch as any).mockResolvedValueOnce({ ok: true, status: 200, json: async () => mockResponse, }); const result = await getInstanceStatus("test-instance"); expect(result).toEqual({ instance: "test-instance", status: "disconnected", }); }); it("should return error status when instance not found", async () => { (global.fetch as any).mockResolvedValueOnce({ ok: false, status: 404, }); const result = await getInstanceStatus("invalid-instance"); expect(result.status).toBe("error"); expect(result.error).toContain("does not exist"); }); it("should return error status on network error", async () => { (global.fetch as any).mockRejectedValueOnce(new Error("Network error")); const result = await getInstanceStatus("test-instance"); expect(result.status).toBe("error"); expect(result.error).toBe("Network error"); }); }); describe("getAllInstancesStatus", () => { it("should return status for all instances", async () => { const mockResponse1 = { instance: { instanceName: "instance1", state: "open" }, }; const mockResponse2 = { instance: { instanceName: "instance2", state: "close" }, }; const mockResponse3 = { instance: { instanceName: "instance3", state: "open" }, }; (global.fetch as any) .mockResolvedValueOnce({ ok: true, json: async () => mockResponse1, }) .mockResolvedValueOnce({ ok: true, json: async () => mockResponse2, }) .mockResolvedValueOnce({ ok: true, json: async () => mockResponse3, }); const results = await getAllInstancesStatus(); expect(results).toHaveLength(3); expect(results[0].status).toBe("connected"); expect(results[1].status).toBe("disconnected"); expect(results[2].status).toBe("connected"); }); }); describe("generateQRCode", () => { it("should generate QR code successfully", async () => { const mockResponse = { pairingCode: "ABC123", code: "xyz789", count: 1, }; (global.fetch as any).mockResolvedValueOnce({ ok: true, status: 200, json: async () => mockResponse, }); const result = await generateQRCode("test-instance"); expect(result).toEqual({ pairingCode: "ABC123", code: "xyz789", count: 1, instance: "test-instance", }); expect(global.fetch).toHaveBeenCalledWith( "https://api.test.com/instance/connect/test-instance", expect.objectContaining({ method: "GET", headers: expect.objectContaining({ apikey: "test-api-key", }), }), ); }); it("should include phone number in query params when provided", async () => { const mockResponse = { pairingCode: "ABC123", code: "xyz789", count: 1, }; (global.fetch as any).mockResolvedValueOnce({ ok: true, status: 200, json: async () => mockResponse, }); await generateQRCode("test-instance", "+5511999999999"); expect(global.fetch).toHaveBeenCalledWith( "https://api.test.com/instance/connect/test-instance?number=%2B5511999999999", expect.any(Object), ); }); it("should throw error when instance not found", async () => { (global.fetch as any).mockResolvedValueOnce({ ok: false, status: 404, }); await expect(generateQRCode("invalid-instance")).rejects.toThrow( "does not exist", ); }); }); describe("disconnectInstance", () => { it("should disconnect instance successfully", async () => { const mockResponse = { status: "SUCCESS", error: false, response: { message: "Instance logged out", }, }; (global.fetch as any).mockResolvedValueOnce({ ok: true, status: 200, json: async () => mockResponse, }); await expect(disconnectInstance("test-instance")).resolves.not.toThrow(); expect(global.fetch).toHaveBeenCalledWith( "https://api.test.com/instance/logout/test-instance", expect.objectContaining({ method: "DELETE", headers: expect.objectContaining({ apikey: "test-api-key", }), }), ); }); it("should throw error when instance not found", async () => { (global.fetch as any).mockResolvedValueOnce({ ok: false, status: 404, }); await expect(disconnectInstance("invalid-instance")).rejects.toThrow( "does not exist", ); }); it("should throw error on network failure", async () => { (global.fetch as any).mockRejectedValueOnce(new Error("Network error")); await expect(disconnectInstance("test-instance")).rejects.toThrow( "Network error", ); }); }); });