import { describe, it, expect, vi, beforeEach } from "vitest";
import { z } from "zod";
// Create mock types
interface MockTool {
name: string;
description: string;
schema: Record<string, unknown>;
handler: (args: unknown) => Promise<{ content: Array<{ type: string; text: string }> }>;
}
// Mock MCP Server
const registeredTools: MockTool[] = [];
const mockServer = {
tool: vi.fn((name: string, description: string, schema: unknown, handler: unknown) => {
registeredTools.push({
name,
description,
schema: schema as Record<string, unknown>,
handler: handler as MockTool["handler"],
});
}),
};
// Mock BirstClient
const mockClient = {
rest: vi.fn(),
genai: vi.fn(),
icw: vi.fn(),
getEnvironment: vi.fn().mockReturnValue("TST"),
setEnvironment: vi.fn(),
};
describe("Discovery Tools", () => {
beforeEach(() => {
vi.clearAllMocks();
registeredTools.length = 0;
});
describe("listSpaces", () => {
it("should register the tool correctly", async () => {
const { registerListSpaces } = await import(
"../../src/tools/discovery/listSpaces.js"
);
registerListSpaces(mockServer as never, mockClient as never);
expect(mockServer.tool).toHaveBeenCalledWith(
"birst_list_spaces",
expect.any(String),
expect.any(Object),
expect.any(Function)
);
});
it("should return list of spaces", async () => {
const { registerListSpaces } = await import(
"../../src/tools/discovery/listSpaces.js"
);
registerListSpaces(mockServer as never, mockClient as never);
const mockSpaces = [
{ id: "space-1", name: "Test Space 1", owner: "user1" },
{ id: "space-2", name: "Test Space 2", owner: "user2" },
];
mockClient.rest.mockResolvedValueOnce(mockSpaces);
const tool = registeredTools.find((t) => t.name === "birst_list_spaces");
const result = await tool!.handler({});
expect(mockClient.rest).toHaveBeenCalledWith("/spaces");
expect(result.content[0].type).toBe("text");
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.count).toBe(2);
expect(parsed.spaces).toHaveLength(2);
});
});
describe("getSpace", () => {
it("should register the tool correctly", async () => {
const { registerGetSpace } = await import(
"../../src/tools/discovery/getSpace.js"
);
registerGetSpace(mockServer as never, mockClient as never);
expect(mockServer.tool).toHaveBeenCalledWith(
"birst_get_space",
expect.any(String),
expect.any(Object),
expect.any(Function)
);
});
it("should return space details", async () => {
const { registerGetSpace } = await import(
"../../src/tools/discovery/getSpace.js"
);
registerGetSpace(mockServer as never, mockClient as never);
const mockSpace = {
id: "space-1",
name: "Test Space",
owner: "user1",
description: "A test space",
timezone: "UTC",
readOnly: false,
};
mockClient.rest.mockResolvedValueOnce(mockSpace);
const tool = registeredTools.find((t) => t.name === "birst_get_space");
const result = await tool!.handler({ spaceId: "space-1" });
expect(mockClient.rest).toHaveBeenCalledWith("/spaces/space-1");
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.space.id).toBe("space-1");
expect(parsed.space.name).toBe("Test Space");
});
});
describe("listReports", () => {
it("should register the tool correctly", async () => {
const { registerListReports } = await import(
"../../src/tools/discovery/listReports.js"
);
registerListReports(mockServer as never, mockClient as never);
expect(mockServer.tool).toHaveBeenCalledWith(
"birst_list_reports",
expect.any(String),
expect.any(Object),
expect.any(Function)
);
});
it("should return paginated list of reports", async () => {
const { registerListReports } = await import(
"../../src/tools/discovery/listReports.js"
);
registerListReports(mockServer as never, mockClient as never);
const mockReports = [
{ id: "report-1", name: "Sales Report", type: "dashboard" },
{ id: "report-2", name: "Inventory Report", type: "report" },
];
mockClient.rest.mockResolvedValueOnce(mockReports);
const tool = registeredTools.find((t) => t.name === "birst_list_reports");
const result = await tool!.handler({
spaceId: "space-1",
resultsPerPage: 100,
currentPage: 0,
});
expect(mockClient.rest).toHaveBeenCalledWith(
"/spaces/space-1/reports",
expect.objectContaining({
queryParams: {
resultsPerPage: 100,
currentPage: 0,
},
})
);
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.reports).toHaveLength(2);
});
});
describe("listCollections", () => {
it("should return list of collections", async () => {
const { registerListCollections } = await import(
"../../src/tools/discovery/listCollections.js"
);
registerListCollections(mockServer as never, mockClient as never);
const mockCollections = [
{ id: "col-1", name: "Sales Dashboards" },
{ id: "col-2", name: "Finance Reports" },
];
mockClient.rest.mockResolvedValueOnce(mockCollections);
const tool = registeredTools.find(
(t) => t.name === "birst_list_collections"
);
const result = await tool!.handler({ spaceId: "space-1" });
expect(mockClient.rest).toHaveBeenCalledWith(
"/spaces/space-1/collections"
);
const parsed = JSON.parse(result.content[0].text);
expect(parsed.success).toBe(true);
expect(parsed.collections).toHaveLength(2);
});
});
});