Skip to the code
cf.

Sleep

Write delay(ms, value), the classic sleep helper. It returns a promise that fulfills with value once ms milliseconds have passed. Without a value, it fulfills with undefined. It never rejects.

Even delay(0) waits for a timer, like setTimeout(fn, 0): the promise doesn't fulfill until that timer fires.

async function countdown() {
  console.log(3);
  await delay(1000);
  console.log(2);
  const word = await delay(1000, "go");
  console.log(word); // "go", two seconds after 3
}

What the tests check

  1. returns a promise
    useFakeTimers();
    expect(delay(100)).toBeInstanceOf(Promise);
    
  2. doesn't fulfill before ms have passed
    const clock = useFakeTimers();
    let done = false;
    delay(100).then(() => {
      done = true;
    });
    await clock.tickAsync(99);
    expect(done).toBe(false);
    
  3. fulfills once ms have passed
    const clock = useFakeTimers();
    let done = false;
    delay(100).then(() => {
      done = true;
    });
    await clock.tickAsync(100);
    expect(done).toBe(true);
    
  4. fulfills with the value it was given
    const clock = useFakeTimers();
    let result;
    delay(50, "ready").then((value) => {
      result = value;
    });
    await clock.tickAsync(50);
    expect(result).toBe("ready");
    
  5. fulfills with undefined when there's no value
    const clock = useFakeTimers();
    let result = "not yet";
    delay(10).then((value) => {
      result = value;
    });
    await clock.tickAsync(10);
    expect(result).toBeUndefined();
    
  6. several delays finish in order of their times
    const clock = useFakeTimers();
    const order = [];
    delay(300, "c").then((value) => order.push(value));
    delay(100, "a").then((value) => order.push(value));
    delay(200, "b").then((value) => order.push(value));
    await clock.tickAsync(300);
    expect(order).toEqual(["a", "b", "c"]);
    
  7. delay(0) still waits for a timer
    const clock = useFakeTimers();
    let done = false;
    delay(0).then(() => {
      done = true;
    });
    await flush();
    expect(done).toBe(false);
    await clock.tickAsync(0);
    expect(done).toBe(true);
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).