avajs/ava

ava + dynamic tests + sinon.useFakeTimers have weird behaviour - tests fail with no clear error

bitliner opened this issue · 1 comments

Version

node v18.17.1

ava 5.3.1

sinon 15.2.0

How to replicate?

const test = require('ava')
const range = n => [...Array(n).keys()]
const sinon = require('sinon')

let clock

test.before(() => {
  const now = new Date(2022, 3, 2) // simulate like it is now "2 april 2022"
  clock = sinon.useFakeTimers(now.getTime())
})
test.after(() => {
  clock.restore()
})

const fakePromise = (input) => new Promise((resolve) => setTimeout(() => resolve(input), 1 * 2000))

// dynamic tests

for (const i of range(15)) {
  test(`test-${i}`, async (t) => {
    const res = await fakePromise(i)

    t.deepEqual(res, i)
  })
}

Results

I get all tests failing with only the following type of message:

test-1

  Error: Promise returned by test never resolved


test-xxx

  Error: Promise returned by test never resolved

Expected

I expect the tests to pass.

It works if sion.useFakeTimers is commented, like the following

const test = require('ava')
const range = n => [...Array(n).keys()]

const fakePromise = (input) => new Promise((resolve) => setTimeout(() => resolve(input), 1 * 2000))

for (const i of range(15)) {
  test(`test-${i}`, async (t) => {
    const res = await fakePromise(i)

    t.deepEqual(res, i)
  })
}

Probably related to the usage of sinon.useFakeTimers().

I made it work with the option shouldAdvanceTime: true

const test = require('ava')
const sinon = require('sinon')

const range = n => [...Array(n).keys()]

let clock

test.before(() => {
  const now = new Date(2022, 3, 2) // simulate like it is now "2 april 2022"
  clock = sinon.useFakeTimers({
    now: now.getTime(),
    shouldAdvanceTime: true
  })
})
test.after(() => {
  clock.restore()
})

const fakePromise = (input) => new Promise((resolve) => setTimeout(() => resolve(input), 1 * 2000))

// dynamic tests

for (const i of range(15)) {
  test(`test-${i}`, async (t) => {
    const res = await fakePromise(i)

    t.deepEqual(res, i)
  })
}