- Implemented a bash script to test n8n API and retrieve credential schemas. - Added types for API responses, Google Calendar, and WhatsApp instances. - Configured Vitest for testing with React and added setup for testing-library.
280 lines
7.5 KiB
TypeScript
280 lines
7.5 KiB
TypeScript
/**
|
|
* 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",
|
|
);
|
|
});
|
|
});
|
|
});
|