Search code examples
javascriptunit-testingsettimeoutjsdomava

Ava test setTimeout() on addEventListener()


I have this function which I want to test with ava and browser-env

function foo () {
  setTimeout(() => {
    const event = new CustomEvent('pushcommand', { detail: 'foo', bubbles: true })
    document.getElementById('command-history').dispatchEvent(event)
  }, 1)
}

My test code is:

import test from 'ava'
import foo from 'foo.js'

test('foo', t => {
  document.body.innerHTML = '<ul id="command-history"></ul>'
  document.getElementById('command-history').addEventListener('pushcommand', event => {
    t.is(event.detail, 'foo')
  })
  foo()
})

But I get the error in ava: Error: Test finished without running any assertions. The code from the event listener is executed, it's just that ava doesn't reach it before exiting the test.

Anyone knows how to fix this?

I tried test.serial, async await, t.end() to no avail. Please help.


Solution

  • async-await can be tricky. the test is probably ending before the async callback is called. since no promise is returned (async) ava doesn't know to wait until the test is complete. something like this should help communicate to ava to wait until the promise finishes

    import test from 'ava'
    import foo from 'foo.js'
    
    function foo () {
      setTimeout(() => {
        const event = new CustomEvent('pushcommand', { detail: 'foo', bubbles: true })
        document.getElementById('command-history').dispatchEvent(event)
      }, 1)
    }
    
    test('foo', async (t) => {
      document.body.innerHTML = '<ul id="command-history"></ul>'
      await new Promise((resolve, reject) => {
        window.addEventListener('error', reject)
        document.getElementById('command-history').addEventListener('pushcommand', event => {
          t.is(event.detail, 'foo')
          resolve()
        })
        foo()
      })
    })