Unit-test a Sume submit-and-poll loop in Vitest with fake replies

Test a Sume polling loop without spending credits: inject the sleep, replay queued then completed replies, and assert next_poll_after_seconds is honored.

5 min readSume
All posts

To test a Sume poll loop without paying for a generation, make the HTTP read and the sleep arguments of your function, then feed it canned status replies. Nothing in the loop needs a network: the documented status fields terminal, sume_status and next_poll_after_seconds are enough to drive it. Teams rebuilding video integrations after the Sora API shutdown on 2026-09-24 are rewriting exactly this loop, so it is worth pinning with a test.

What the test should pin

The Sume docs give the loop its contract: poll status_url, stop when terminal is true, sleep next_poll_after_seconds when present and back off otherwise, and read the result only for a completed job.

  • A queued reply must not end the loop; queued is a normal accepted state.
  • A reply with next_poll_after_seconds must set the next sleep.
  • A failed or canceled terminal reply must come back to the caller, not throw from a result read, because GET /v1/jobs/:id/result answers 409 job_not_completed for them.

The loop and the test

The sleep is injected, so the test finishes instantly and records every wait it was asked to make. If you use createSumeClient, its fetch option is the matching seam for faking the transport.

import { expect, test } from "vitest";

export async function pollJob(
  get: (path: string) => Promise<any>,
  id: string,
  sleep = (s: number) => new Promise((r) => setTimeout(r, s * 1000)),
) {
  for (;;) {
    const s = await get(`/v1/jobs/${id}/status`);
    if (s.terminal) return s;
    await sleep(s.next_poll_after_seconds ?? 5);
  }
}

test("polls to terminal and honors next_poll_after_seconds", async () => {
  const replies = [
    { terminal: false, sume_status: "queued", next_poll_after_seconds: 7 },
    { terminal: true, sume_status: "completed" },
  ];
  const waits: number[] = [];
  const s = await pollJob(async () => replies.shift(), "job_1", async (n) => {
    waits.push(n);
  });
  expect(s.sume_status).toBe("completed");
  expect(waits).toEqual([7]);
});

Cases worth adding

Add one test per terminal state and one for a deadline. Keep the deadline in your client: a client timeout does not cancel the job, it only stops you watching, so the test should assert that your code stores the job id before giving up.

Test cases for a Sume poll loop (read 2026-10-03)
CaseFake replyExpected behavior
Queued then donequeued, then completedLoop continues, then returns
Server-paced waitnext_poll_after_seconds setSleeps that many seconds
Failed jobterminal true, sume_status failedReturns the record for error handling
Your deadline hitnever terminalThrows your timeout, keeps the job id

Sources

Related posts

More in Developers

All Developers posts

Written by Sume