diff --git a/extensions/xai/video-generation-provider.test.ts b/extensions/xai/video-generation-provider.test.ts index af4e9055ebb..e73b8160a1c 100644 --- a/extensions/xai/video-generation-provider.test.ts +++ b/extensions/xai/video-generation-provider.test.ts @@ -15,6 +15,40 @@ beforeAll(async () => { installProviderHttpMockCleanup(); +function requirePostJsonCall(index = 0): { + url?: string; + body?: Record; +} { + const params = (postJsonRequestMock.mock.calls as unknown as Array<[unknown]>)[index]?.[0] as + | { + url?: string; + body?: Record; + } + | undefined; + if (!params) { + throw new Error(`Expected postJsonRequest call ${index}`); + } + return params; +} + +function requireFetchInitCall(index: number): { + url?: string; + init?: { method?: string }; + timeoutMs?: number; +} { + const call = ( + fetchWithTimeoutMock.mock.calls as unknown as Array<[string, { method?: string }, number]> + )[index]; + if (!call) { + throw new Error(`Expected fetchWithTimeout call ${index}`); + } + return { + url: call[0], + init: call[1], + timeoutMs: call[2], + }; +} + describe("xai video generation provider", () => { it("declares explicit mode capabilities", () => { expectExplicitVideoGenerationCapabilities(buildXaiVideoGenerationProvider()); @@ -53,33 +87,21 @@ describe("xai video generation provider", () => { resolution: "720P", }); - expect(postJsonRequestMock).toHaveBeenCalledWith( - expect.objectContaining({ - url: "https://api.x.ai/v1/videos/generations", - body: expect.objectContaining({ - model: "grok-imagine-video", - prompt: "A tiny robot crab crossing a moonlit tide pool", - duration: 6, - aspect_ratio: "16:9", - resolution: "720p", - }), - }), - ); - expect(fetchWithTimeoutMock).toHaveBeenNthCalledWith( - 1, - "https://api.x.ai/v1/videos/req_123", - expect.objectContaining({ method: "GET" }), - 120000, - fetch, - ); + const createRequest = requirePostJsonCall(); + expect(createRequest.url).toBe("https://api.x.ai/v1/videos/generations"); + expect(createRequest.body?.model).toBe("grok-imagine-video"); + expect(createRequest.body?.prompt).toBe("A tiny robot crab crossing a moonlit tide pool"); + expect(createRequest.body?.duration).toBe(6); + expect(createRequest.body?.aspect_ratio).toBe("16:9"); + expect(createRequest.body?.resolution).toBe("720p"); + const pollRequest = requireFetchInitCall(0); + expect(pollRequest.url).toBe("https://api.x.ai/v1/videos/req_123"); + expect(pollRequest.init?.method).toBe("GET"); + expect(pollRequest.timeoutMs).toBe(120000); expect(result.videos[0]?.mimeType).toBe("video/webm"); expect(result.videos[0]?.fileName).toBe("video-1.webm"); - expect(result.metadata).toEqual( - expect.objectContaining({ - requestId: "req_123", - mode: "generate", - }), - ); + expect(result.metadata?.requestId).toBe("req_123"); + expect(result.metadata?.mode).toBe("generate"); }); it("sends a single unroled image as xAI first-frame image-to-video", async () => { @@ -113,23 +135,13 @@ describe("xai video generation provider", () => { inputImages: [{ buffer: Buffer.from("png-bytes"), mimeType: "image/png" }], }); - const body = postJsonRequestMock.mock.calls[0]?.[0]?.body as Record; - expect(postJsonRequestMock).toHaveBeenCalledWith( - expect.objectContaining({ - url: "https://api.x.ai/v1/videos/generations", - body: expect.objectContaining({ - image: { - url: expect.stringMatching(/^data:image\/png;base64,/), - }, - }), - }), - ); + const request = requirePostJsonCall(); + expect(request.url).toBe("https://api.x.ai/v1/videos/generations"); + const image = request.body?.image as { url?: string } | undefined; + expect(image?.url).toMatch(/^data:image\/png;base64,/u); + const body = request.body ?? {}; expect(body).not.toHaveProperty("reference_images"); - expect(result.metadata).toEqual( - expect.objectContaining({ - mode: "generate", - }), - ); + expect(result.metadata?.mode).toBe("generate"); }); it("sends reference_image roles through xAI reference_images mode", async () => { @@ -169,27 +181,18 @@ describe("xai video generation provider", () => { ], }); - const body = postJsonRequestMock.mock.calls[0]?.[0]?.body as Record; - expect(postJsonRequestMock).toHaveBeenCalledWith( - expect.objectContaining({ - url: "https://api.x.ai/v1/videos/generations", - body: expect.objectContaining({ - reference_images: [ - { url: "https://example.com/subject.png" }, - { url: "https://example.com/style.png" }, - ], - duration: 10, - aspect_ratio: "9:16", - resolution: "720p", - }), - }), - ); + const request = requirePostJsonCall(); + expect(request.url).toBe("https://api.x.ai/v1/videos/generations"); + expect(request.body?.reference_images).toEqual([ + { url: "https://example.com/subject.png" }, + { url: "https://example.com/style.png" }, + ]); + expect(request.body?.duration).toBe(10); + expect(request.body?.aspect_ratio).toBe("9:16"); + expect(request.body?.resolution).toBe("720p"); + const body = request.body ?? {}; expect(body).not.toHaveProperty("image"); - expect(result.metadata).toEqual( - expect.objectContaining({ - mode: "referenceToVideo", - }), - ); + expect(result.metadata?.mode).toBe("referenceToVideo"); }); it("rejects mixed xAI first-frame and reference-image roles", async () => { @@ -244,14 +247,9 @@ describe("xai video generation provider", () => { inputVideos: [{ url: "https://example.com/input.mp4" }], }); - expect(postJsonRequestMock).toHaveBeenCalledWith( - expect.objectContaining({ - url: "https://api.x.ai/v1/videos/extensions", - body: expect.objectContaining({ - video: { url: "https://example.com/input.mp4" }, - duration: 8, - }), - }), - ); + const request = requirePostJsonCall(); + expect(request.url).toBe("https://api.x.ai/v1/videos/extensions"); + expect(request.body?.video).toEqual({ url: "https://example.com/input.mp4" }); + expect(request.body?.duration).toBe(8); }); });