Skip to content

add section to docs on testing components that include promises #151

Closed
@lmiller1990

Description

@lmiller1990

First, I am not sure if this is something vue-test-utils should do or something the test runner should handle. It's just an idea I had to solve a problem I found a lot while using vue-test-utils.

A number of libraries (for example vee validate, which I have been using heavily in my app) rely on promises. In the case of vee validate, errors are rendered async. vue-test-utils does everything sync. Another common test case is asserting some UI changed based on a mock API response, that uses a promise.

Both these cases require the test to wait for a promise to resolve (even if it is one that resolves almost immediately). vue-test-utils is all sync, I have to use the test runner (in this case jest) to await the promise, or the wrapper.vm is not updated.

The below example shows the first case (failing for the reason outlined above) and a workaround.

My original idea was a triggerAsync method:

wrapper.find('input').triggerAsync('click', (done) => {
  // wait for promises to resolve
  // wrapper.update() so computed/data values, and UI is updated
  // assertions
  done()
})

However I am starting to think I am heading down the wrong path.

Example:
Component

<template>
  <div id="app">
    {{ msg }}
    <button @click="handle">Button</button>
</template>

<script>
export default {
  name: 'app',

  data () {
    return {
      msg: '',
    }
  },

  methods: {
    promise () {
      return new Promise(res => {
        res()
      })
    },

    handle () {
      this.promise()
        .then(() => {
          this.msg = 'testing'
        })
    }
  }
}
</script>

Test:

import { shallow } from 'vue-test-utils'
import App from './App'

describe('App', () => {
  // fails because async promise
  it('sets some text', () => {
    const wrapper = shallow(App)

    wrapper.find('button').trigger('click')

    expect(wrapper.vm.msg).toBe('testing')
  })

// returning a promise in jest lets this pass
it('sets some text', () => {
    const wrapper = shallow(App)

    return new Promise(res => {
      wrapper.find('button').trigger('click')
      res()
    })
    .then(() => {
       expect(wrapper.vm.msg).toBe('testing')
    })
  })
})

https://github.com/lmiller1990/vue-test-utils-async for example using vee-vadidate

Or, am I venturing out of the realm of unit test into e2e test here?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions