Giter Club home page Giter Club logo

Comments (17)

skray avatar skray commented on September 26, 2024 32

Sorry, forgot to close this after merging #86.

Also thanks @fartek for the example, I've actually been a fan of using async/await in my tests, so I don't have to wrap anything in a callback:

it('should await synchronously', async () => {
  const wrapper = mount(MyComponent)
  
  await wrapper.vm.$nextTick()

  // assert things like data loading properly
}

from vue-test-utils.

chlab avatar chlab commented on September 26, 2024 14

Doesn't work either:

await flushPromises()
await flushPromises()
expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')

edit: huh, this works though:

flushPromises().then(() => {
  expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
})

Any idea why the async/await version wouldn't work (I'm using async/await everywhere else in my code)? 🤔

from vue-test-utils.

lzhoucs avatar lzhoucs commented on September 26, 2024 10

We ran into a similar problem recently, this is what we found:
Instead of:

await wrapper.vm.$nextTick();

Use:

// mount your component
await new Promise(resolve => setTimeout(resolve));
// promise should resolved and you can assert things like data loading properly

instead.

from vue-test-utils.

eddyerburgh avatar eddyerburgh commented on September 26, 2024 6

Use flush-promises:

npm install --save-dev flush-promises
import flushPromises from 'flush-promises'

  test('data is loaded and rendered', async () => {
    const store = createNamespacedStore('@/store/modules/Profile', 'Profile')
    const wrapper = mount(Profile, {
      store,
      localVue,
      mocks: {
        $t: jest.fn()
      }
    })
    await flushPromises()
    expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
  })
})

from vue-test-utils.

mixn avatar mixn commented on September 26, 2024 3

I can +1 on @chlab’s use–case, works for me as a thenable, unfortunately doesn’t with await. 🤔

from vue-test-utils.

fartek avatar fartek commented on September 26, 2024 2

You can handle wrapper.vm.$nextTick by using your test runner's done/end functions.
For instance with Ava you would write a test:

// use 'test.cb' instead of just 'test' as it tells Ava to wait for a callback
test.cb('A $nextTick test that will pass', t => {
  const wrapper = shallow(MyComponent);
  wrapper.vm.$nextTick(() => {
    t.pass(); // passes the test - you can have any assertion here
    t.end(); // ends the test
  });
});

And other test runners also must have similar methods for testing async JS.

from vue-test-utils.

hisuwh avatar hisuwh commented on September 26, 2024 2

I expect people finding this works are getting a false positive:

flushPromises().then(() => {
  expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
})

This made my test pass but if I returned the promise in my jest test as my linter told me to do, then the test failed again as before:

return flushPromises().then(() => {
  expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
})

from vue-test-utils.

skray avatar skray commented on September 26, 2024 1

I'd be happy to, I'll try to get something up tonight.

from vue-test-utils.

eddyerburgh avatar eddyerburgh commented on September 26, 2024

Thanks for the issue 🙂

You're right, update only re renders the DOM. It doesn't affect async functions, like promises.

I think this should be added to the docs. Would you like to make a PR clarifying that update does not do this?

from vue-test-utils.

chlab avatar chlab commented on September 26, 2024

Sorry for posting this here, but I'm having trouble with this exact case. I am writing a test for a component that loads data from an API and displays that data in a form. I'm mocking the data access layer and resolving the promise right away. With the code above, the value is never there yet and my test fails.

Here's the test:

// ...imports

describe('Profile page', () => {
  const localVue = createLocalVue()
  localVue.use(Vuex)

  // mock api data
  jest.mock('@/data/PersonData', () => {
    return {
      getOwnerData () {
        return Promise.resolve({ email: '[email protected]' })
      }
    }
  })

  test('data is loaded and rendered', async () => {
    const store = createNamespacedStore('@/store/modules/Profile', 'Profile')
    const wrapper = mount(Profile, {
      store,
      localVue,
      mocks: {
        $t: jest.fn()
      }
    })

    await wrapper.vm.$nextTick()
    // this fails:
    expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
    // this passes:
    setTimeout(() => {
      expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
    }, 10)
  })
})

Any help on this?

from vue-test-utils.

chlab avatar chlab commented on September 26, 2024

Thanks @eddyerburgh. Unfortunately, it still doesn't work. I have the await flushPromises() right before the expect. Again, if I put the expect into the setTimeout block, even with 1ms, the test passes.

It may be relevant to note that the component I'm testing calls the mocked function getOwnerData() in it's beforeMount hook. So it's being invoked automatically. All the examples I'm seeing with jest are invoking the async methods themselves, like:

expect(wrapper.load()).resolves.toBe(...)

from vue-test-utils.

eddyerburgh avatar eddyerburgh commented on September 26, 2024

Try calling flushPromises twice.

Here's an example test for a component that runs an async function in beforeMounthttps://github.com/eddyerburgh/vue-hackernews-chapter-6/blob/master/src/views/__tests__/ItemList.spec.js#L65

from vue-test-utils.

eddyerburgh avatar eddyerburgh commented on September 26, 2024

@mixn What test runner/ browser environment are you using?

from vue-test-utils.

stwilz avatar stwilz commented on September 26, 2024

I've just been dealing with a similar problem and didn't want to hack around it using timeout's (nextTick also didn't work). I fixed this by exposing the promise in my components data and referencing it in my test.
form.js

  data () {
    return {
      submitPromise: true
    }
  },

  methods: {
    submit () {
      this.submitPromise = this.$validator
        .validateAll()
        .then(() => {
          if (!this.credentialsIncorrect && !this.errors.items.length) {
            this.$emit('onCredentialsCorrect', this.activationForm)
          } else {
            this.$emit('onCredentialsIncorrect', this.errors.items)
          }
          return Promise.resolve()
        })
      return this.submitPromise
    }
  },

form.test.js

  it('will run test after promise is resolved', () => {
    form.trigger('submit')
    return wrapper.vm.submitPromise
      .then(()=>{
        expect(wrapper.emitted('onCredentialsCorrect')).toBeTruthy()
      })
  })

from vue-test-utils.

guguji5 avatar guguji5 commented on September 26, 2024

Hi @chlab, thanks for you post. it saves my day.

flushPromises().then(() => {
expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
})

from vue-test-utils.

omeryousaf avatar omeryousaf commented on September 26, 2024

wondering if including import 'babel-polyfill'; would help in @chlab 's case. 🤔

from vue-test-utils.

sushmitha-b-s avatar sushmitha-b-s commented on September 26, 2024

Doesn't work either:

await flushPromises()
await flushPromises()
expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')

edit: huh, this works though:

flushPromises().then(() => {
  expect(wrapper.find({ ref: 'emailField' }).text()).toBe('[email protected]')
})

Any idea why the async/await version wouldn't work (I'm using async/await everywhere else in my code)?

Thanks @chlab . I had a same issue and this worked well.

from vue-test-utils.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.