-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathuseManagedTools.test.tsx
More file actions
129 lines (105 loc) · 3.84 KB
/
Copy pathuseManagedTools.test.tsx
File metadata and controls
129 lines (105 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @vitest-environment jsdom
*/
import { describe, it, expect } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { useManagedTools } from "../../react/useManagedTools.js";
import { createStore, type StoreApi } from "zustand/vanilla";
import type { ManagedToolsState } from "../../mcp/state/managedToolsState.js";
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
/**
* Mock ManagedToolsState: getStore(), getTools(), refresh(), setMetadata(), destroy().
* Not typed as implements ManagedToolsState because the real class has private fields.
*/
class MockManagedToolsState {
private store: StoreApi<{ tools: Tool[] }>;
constructor() {
this.store = createStore<{ tools: Tool[] }>()((_set) => ({ tools: [] }));
}
getStore() {
return {
getState: () => this.store.getState(),
subscribe: (listener: () => void) => this.store.subscribe(listener),
};
}
getTools(): Tool[] {
return this.store.getState().tools;
}
setTools(tools: Tool[]): void {
this.store.setState({ tools });
}
setMetadata(): void {}
async refresh(): Promise<Tool[]> {
return this.getTools();
}
destroy(): void {
this.store.setState({ tools: [] });
}
}
describe("useManagedTools", () => {
it("returns empty tools and no-op refresh when manager is null or undefined", async () => {
const { result: resultNull } = renderHook(() => useManagedTools(null));
expect(resultNull.current.tools).toEqual([]);
const fromNull = await resultNull.current.refresh();
expect(fromNull).toEqual([]);
const { result: resultUndef } = renderHook(() =>
useManagedTools(undefined),
);
expect(resultUndef.current.tools).toEqual([]);
const fromUndef = await resultUndef.current.refresh();
expect(fromUndef).toEqual([]);
});
it("syncs initial tools from manager store", () => {
const manager = new MockManagedToolsState();
manager.setTools([
{ name: "a", inputSchema: { type: "object" as const } },
{ name: "b", inputSchema: { type: "object" as const } },
]);
const { result } = renderHook(() =>
useManagedTools(manager as unknown as ManagedToolsState),
);
expect(result.current.tools).toHaveLength(2);
expect(result.current.tools.map((t) => t.name)).toEqual(["a", "b"]);
});
it("updates tools when manager store updates", async () => {
const manager = new MockManagedToolsState();
manager.setTools([
{ name: "first", inputSchema: { type: "object" as const } },
]);
const { result } = renderHook(() =>
useManagedTools(manager as unknown as ManagedToolsState),
);
expect(result.current.tools).toHaveLength(1);
expect(result.current.tools[0]?.name).toBe("first");
await act(async () => {
(manager as MockManagedToolsState).setTools([
{ name: "first", inputSchema: { type: "object" as const } },
{ name: "second", inputSchema: { type: "object" as const } },
]);
});
expect(result.current.tools).toHaveLength(2);
expect(result.current.tools.map((t) => t.name)).toEqual([
"first",
"second",
]);
});
it("refresh returns tools from manager", async () => {
const manager = new MockManagedToolsState();
manager.setTools([{ name: "x", inputSchema: { type: "object" as const } }]);
const { result } = renderHook(() =>
useManagedTools(manager as unknown as ManagedToolsState),
);
expect(result.current.tools).toHaveLength(1);
await act(async () => {
(manager as MockManagedToolsState).setTools([
{ name: "x", inputSchema: { type: "object" as const } },
{ name: "y", inputSchema: { type: "object" as const } },
]);
});
await act(async () => {
const next = await result.current.refresh();
expect(next).toHaveLength(2);
});
expect(result.current.tools).toHaveLength(2);
});
});