
























@@ -30,9 +30,37 @@ function installXSearchFetch(payload?: Record<string, unknown>) {
3030return mockFetch;
3131}
323233+function firstFetchCall(mockFetch: ReturnType<typeof installXSearchFetch>) {
34+const [call] = mockFetch.mock.calls;
35+if (!call) {
36+throw new Error("expected x_search fetch call");
37+}
38+return call;
39+}
40+41+function firstFetchUrl(mockFetch: ReturnType<typeof installXSearchFetch>) {
42+const [url] = firstFetchCall(mockFetch);
43+return String(url);
44+}
45+46+function firstFetchInit(mockFetch: ReturnType<typeof installXSearchFetch>): RequestInit {
47+const [, init] = firstFetchCall(mockFetch);
48+if (!init || typeof init !== "object" || Array.isArray(init)) {
49+throw new Error("expected x_search fetch init");
50+}
51+return init as RequestInit;
52+}
53+54+function firstAuthorizationHeader(mockFetch: ReturnType<typeof installXSearchFetch>) {
55+const headers = firstFetchInit(mockFetch).headers;
56+if (!headers || typeof headers !== "object" || Array.isArray(headers)) {
57+throw new Error("expected x_search request headers");
58+}
59+return (headers as Record<string, string>).Authorization;
60+}
61+3362function parseFirstRequestBody(mockFetch: ReturnType<typeof installXSearchFetch>) {
34-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
35-const requestBody = request?.body;
63+const requestBody = firstFetchInit(mockFetch).body;
3664return JSON.parse(typeof requestBody === "string" ? requestBody : "{}") as Record<
3765string,
3866unknown
@@ -81,10 +109,7 @@ describe("xai x_search tool", () => {
81109query: "auth profile search",
82110});
8311184-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
85-expect((request?.headers as Record<string, string> | undefined)?.Authorization).toBe(
86-"Bearer xai-profile-key",
87-);
112+expect(firstAuthorizationHeader(mockFetch)).toBe("Bearer xai-profile-key");
88113});
8911490115it("enables x_search when the xAI plugin web search key is configured", () => {
@@ -139,7 +164,7 @@ describe("xai x_search tool", () => {
139164});
140165141166expect(mockFetch).toHaveBeenCalled();
142-expect(String(mockFetch.mock.calls[0]?.[0])).toContain("api.x.ai/v1/responses");
167+expect(firstFetchUrl(mockFetch)).toContain("api.x.ai/v1/responses");
143168const body = parseFirstRequestBody(mockFetch);
144169expect(body.model).toBe("grok-4-1-fast-non-reasoning");
145170expect(body.max_turns).toBe(2);
@@ -184,7 +209,7 @@ describe("xai x_search tool", () => {
184209query: "base url route",
185210});
186211187-expect(String(mockFetch.mock.calls[0]?.[0])).toBe("https://api.x.ai/xai-search/v1/responses");
212+expect(firstFetchUrl(mockFetch)).toBe("https://api.x.ai/xai-search/v1/responses");
188213});
189214190215it("falls back to Grok web search baseUrl for x_search", async () => {
@@ -208,7 +233,7 @@ describe("xai x_search tool", () => {
208233query: "legacy base url route",
209234});
210235211-expect(String(mockFetch.mock.calls[0]?.[0])).toBe("https://api.x.ai/legacy/v1/responses");
236+expect(firstFetchUrl(mockFetch)).toBe("https://api.x.ai/legacy/v1/responses");
212237});
213238214239it("shares plugin webSearch.baseUrl with x_search when xSearch.baseUrl is unset", async () => {
@@ -237,7 +262,7 @@ describe("xai x_search tool", () => {
237262query: "shared base url route",
238263});
239264240-expect(String(mockFetch.mock.calls[0]?.[0])).toBe("https://api.x.ai/shared/v1/responses");
265+expect(firstFetchUrl(mockFetch)).toBe("https://api.x.ai/shared/v1/responses");
241266});
242267243268it("reuses the xAI plugin web search key for x_search requests", async () => {
@@ -262,10 +287,7 @@ describe("xai x_search tool", () => {
262287query: "latest post from huntharo",
263288});
264289265-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
266-expect((request?.headers as Record<string, string> | undefined)?.Authorization).toBe(
267-"Bearer xai-plugin-key",
268-);
290+expect(firstAuthorizationHeader(mockFetch)).toBe("Bearer xai-plugin-key");
269291});
270292271293it("prefers the active runtime config for shared xAI keys", async () => {
@@ -303,10 +325,7 @@ describe("xai x_search tool", () => {
303325query: "runtime key search",
304326});
305327306-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
307-expect((request?.headers as Record<string, string> | undefined)?.Authorization).toBe(
308-"Bearer x-search-runtime-key",
309-);
328+expect(firstAuthorizationHeader(mockFetch)).toBe("Bearer x-search-runtime-key");
310329});
311330312331it("reuses the legacy grok web search key for x_search requests", async () => {
@@ -329,10 +348,7 @@ describe("xai x_search tool", () => {
329348query: "latest legacy-key post from huntharo",
330349});
331350332-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
333-expect((request?.headers as Record<string, string> | undefined)?.Authorization).toBe(
334-"Bearer xai-legacy-key",
335-);
351+expect(firstAuthorizationHeader(mockFetch)).toBe("Bearer xai-legacy-key");
336352});
337353338354it("uses migrated runtime auth when the source config still carries legacy x_search apiKey", async () => {
@@ -367,10 +383,7 @@ describe("xai x_search tool", () => {
367383query: "migrated runtime auth",
368384});
369385370-const request = mockFetch.mock.calls[0]?.[1] as RequestInit | undefined;
371-expect((request?.headers as Record<string, string> | undefined)?.Authorization).toBe(
372-"Bearer migrated-runtime-key",
373-);
386+expect(firstAuthorizationHeader(mockFetch)).toBe("Bearer migrated-runtime-key");
374387});
375388376389it("rejects invalid date ordering before calling xAI", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。