@@ -195,6 +195,56 @@ describe("xai video generation provider", () => {
|
195 | 195 | ).rejects.toThrow("xAI video generation response malformed"); |
196 | 196 | }); |
197 | 197 | |
| 198 | +it("normalizes the xAI 'pending' poll status to 'processing' and keeps polling until done", async () => { |
| 199 | +postJsonRequestMock.mockResolvedValue({ |
| 200 | +response: { |
| 201 | +json: async () => ({ |
| 202 | +request_id: "req_pending", |
| 203 | +}), |
| 204 | +}, |
| 205 | +release: vi.fn(async () => {}), |
| 206 | +}); |
| 207 | +fetchWithTimeoutMock |
| 208 | +// First poll: in-progress payload mirroring xAI's real shape |
| 209 | +.mockResolvedValueOnce({ |
| 210 | +json: async () => ({ |
| 211 | +request_id: "req_pending", |
| 212 | +status: "pending", |
| 213 | +progress: 42, |
| 214 | +}), |
| 215 | +}) |
| 216 | +// Second poll: complete |
| 217 | +.mockResolvedValueOnce({ |
| 218 | +json: async () => ({ |
| 219 | +request_id: "req_pending", |
| 220 | +status: "done", |
| 221 | +video: { url: "https://cdn.x.ai/video-pending.mp4" }, |
| 222 | +progress: 100, |
| 223 | +}), |
| 224 | +}) |
| 225 | +// Download |
| 226 | +.mockResolvedValueOnce({ |
| 227 | +headers: new Headers({ "content-type": "video/mp4" }), |
| 228 | +arrayBuffer: async () => Buffer.from("mp4-bytes"), |
| 229 | +}); |
| 230 | + |
| 231 | +const provider = buildXaiVideoGenerationProvider(); |
| 232 | +const result = await provider.generateVideo({ |
| 233 | +provider: "xai", |
| 234 | +model: "grok-imagine-video", |
| 235 | +prompt: "Pending then done", |
| 236 | +cfg: {}, |
| 237 | +durationSeconds: 6, |
| 238 | +aspectRatio: "9:16", |
| 239 | +resolution: "720P", |
| 240 | +}); |
| 241 | + |
| 242 | +// Two poll calls (one pending, one done) — not throwing on "pending" |
| 243 | +expect((fetchWithTimeoutMock.mock.calls as unknown[]).length).toBeGreaterThanOrEqual(2); |
| 244 | +expect(result.videos[0]?.mimeType).toBe("video/mp4"); |
| 245 | +expect(result.metadata?.requestId).toBe("req_pending"); |
| 246 | +}); |
| 247 | + |
198 | 248 | it("sends a single unroled image as xAI first-frame image-to-video", async () => { |
199 | 249 | postJsonRequestMock.mockResolvedValue({ |
200 | 250 | response: { |
|