-
Notifications
You must be signed in to change notification settings - Fork 359
Expand file tree
/
Copy pathuseCreateNewChatThread.test.tsx
More file actions
114 lines (97 loc) · 3.37 KB
/
Copy pathuseCreateNewChatThread.test.tsx
File metadata and controls
114 lines (97 loc) · 3.37 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
import { act, renderHook } from "@testing-library/react";
import { afterEach, expect, test, vi } from "vitest";
import type { Source } from "./types";
import { DISABLED_MCP_SERVER_IDS_LOCAL_STORAGE_KEY } from "./constants";
const mocks = vi.hoisted(() => ({
createChat: vi.fn(),
createUIMessage: vi.fn(),
push: vi.fn(),
setChatState: vi.fn(),
toast: vi.fn(),
}));
vi.mock("next/navigation", () => ({
useRouter: () => ({ push: mocks.push }),
}));
vi.mock("@/components/hooks/use-toast", () => ({
useToast: () => ({ toast: mocks.toast }),
}));
vi.mock("./actions", () => ({
createChat: mocks.createChat,
}));
vi.mock("@/lib/utils", () => ({
isServiceError: () => false,
createPathWithQueryParams: (path: string) => path,
}));
vi.mock("./utils", () => ({
createUIMessage: mocks.createUIMessage,
getAllMentionElements: () => [],
slateContentToString: () => "",
}));
vi.mock("usehooks-ts", () => ({
useSessionStorage: () => [null, mocks.setChatState],
}));
const { useCreateNewChatThread } = await import("./useCreateNewChatThread");
afterEach(() => {
window.localStorage.clear();
vi.clearAllMocks();
});
test("createChatFromSource preserves disabled MCP servers from local storage", async () => {
const disabledMcpServerIds = ["linear", "github"];
window.localStorage.setItem(
DISABLED_MCP_SERVER_IDS_LOCAL_STORAGE_KEY,
JSON.stringify(disabledMcpServerIds),
);
mocks.createChat.mockResolvedValue({ id: "chat-1" });
mocks.createUIMessage.mockReturnValue({ id: "initial-message" });
const { result } = renderHook(() => useCreateNewChatThread());
const source: Source = {
type: "file",
repo: "github.com/sourcebot-dev/sourcebot",
path: "packages/web/src/auth.ts",
name: "auth.ts",
revision: "main",
};
await act(async () => {
await result.current.createChatFromSource(source);
});
expect(mocks.createUIMessage).toHaveBeenCalledWith(
"Explain this selected code.",
[],
[],
disabledMcpServerIds,
[],
[source],
);
expect(mocks.setChatState).toHaveBeenCalledWith({
inputMessage: { id: "initial-message" },
selectedSearchScopes: [],
disabledMcpServerIds,
});
});
test("createChatFromSource ignores duplicate calls while chat creation is pending", async () => {
let resolveCreateChat: ((value: { id: string }) => void) | undefined;
mocks.createChat.mockImplementation(() => new Promise((resolve) => {
resolveCreateChat = resolve;
}));
mocks.createUIMessage.mockReturnValue({ id: "initial-message" });
const { result } = renderHook(() => useCreateNewChatThread());
const source: Source = {
type: "file",
repo: "github.com/sourcebot-dev/sourcebot",
path: "packages/web/src/auth.ts",
name: "auth.ts",
revision: "main",
};
let firstCreate: Promise<void> | undefined;
let secondCreate: Promise<void> | undefined;
act(() => {
firstCreate = result.current.createChatFromSource(source);
secondCreate = result.current.createChatFromSource(source);
});
expect(mocks.createChat).toHaveBeenCalledTimes(1);
resolveCreateChat?.({ id: "chat-1" });
await act(async () => {
await Promise.all([firstCreate, secondCreate]);
});
expect(mocks.push).toHaveBeenCalledTimes(1);
});