Vue-test-utils: setProps and setData error in beta.30 version

Created on 4 Dec 2019  路  22Comments  路  Source: vuejs/vue-test-utils

Version

1.0.0-beta.29

Reproduction link

https://github.com/coreui/coreui-vue/tree/bc1cf959325aee78d692e000184825c43294e158

Steps to reproduce

  1. clone repo: https://github.com/coreui/coreui-vue/tree/bc1cf959325aee78d692e000184825c43294e158
  2. npm i
  3. npm run test (then all test passes)
  4. update @vue-test-utils to beta.30
  5. npm run test

What is expected?

beta.30 version doesn't break existing tests

What is actually happening?

beta.30 version breaks existing tests


In beta.29 all my tests are passing, after update to beta.30 many tests that are using "setProps" and "setData" methods are failing.

P.S. there is no possibility to chose beta.30 from versions in issue generator.

docs sync

Most helpful comment

Maybe it was set by setData method 馃槀

All 22 comments

I'm having the same problem with you. You can try using nextTick as a workaround.

@woothu this is expected behaviour, as beta.29 still had synchronous updates as the default behaviour, whereas beta.30 removes the option entirely and only allows asynchronous updates. This requires waiting for Vue.nextTick() or wrapper.vm.$nextTick() after triggering DOM changes.

Because this project is still in beta, there are no guarantees of backwards-compatibility between versions.

@vvanpo Moving from synchronous to asynchronous updates is a huge change, especially when users will not know why all their tests are now breaking. In my case it broke 56 of my 70 tests, so updating each test with Vue.nextTick() was not a good option. beta.30 also seems to be handling Vue transitions differently, causing further breaking tests. I have now learnt my lesson and limited my package.json to beta.29.

@DoubleWombat Yep, I can sympathize. It's an unfortunate outcome of a core Vue project being kept in beta while the rest of the Vue ecosystem has long had stable releases. Everyone is in the same boat, most will have to pin their version to beta.29 until they can find the time to update all of their tests (for example, at my work we have a project with over 2000 tests using @vue/test-utils, which all need to be migrated).

To aid in migration, you can update your test suites piecemeal by setting sync: false in the mounting options passed to mount() or shallowMount(). This ensures the tests are forwards-compatible, meaning once all your tests are written this way the upgrade to beta.30 should be seamless.

Is there a reason to completely remove the synchronous option? Is it just down to Vue itself? For tests it would be nice if there was an option I could force the state without having to wait for the next tick

@woothu this is expected behaviour, as beta.29 still had synchronous updates as the default behaviour, whereas beta.30 removes the option entirely and only allows asynchronous updates. This requires waiting for Vue.nextTick() or wrapper.vm.$nextTick() after triggering DOM changes.

Because this project is still in beta, there are no guarantees of backwards-compatibility between versions.

It would be nice if you mention breaking changes on release notes, especially as your tool is widely used on user's production environments.

Oh I see. Maybe something wrong with the release process because the script looks fine https://github.com/vuejs/vue-test-utils/blob/dev/package.json#L21

Maybe it was set by setData method 馃槀

Is there a reason to completely remove the synchronous option? Is it just down to Vue itself? For tests it would be nice if there was an option I could force the state without having to wait for the next tick

@stats94 There is some background here: https://github.com/vuejs/vue-test-utils/issues/1137

I agree that synchronous updates were very convenient, but it seems that maintaining a synchronous capability within Vue.js purely for testing was troublesome.

The benefit of always writing async tests is that you can be more confident that you are not overlooking subtle race conditions. Additionally, I think it can help programmers understand their components better, as it forces them to think about when DOM updates are triggered.

We've encountered issues (after adding a nextTick wait after all set data/props and event triggers), but now the transition hooks afterLeave and afterEnter no longer fire (cannot be tested), no matter how many nextTicks or sleeps we do (this is without the transition stubs)

@tmorehouse You can try to stub the transition component. It's much simpler than the old TransitionStub but it works for me. For TransitionGroup, I guess we can do the same.

stubs: {
  transition: {
    render: function (h) {
      return this.$options._renderChildren
    }
  }
}

Note: You still need to await wrapper.vm.$nextTick() though.

Hi @hiendv and @tmorehouse! Would it be possible for either of you to provide me with a reproduction repo that demonstrates issues with afterLeave/afterEnter for transition components? I would love to investigate and then put @hiendv's workaround into the docs.

@JessicaSachs
Sorry for my mistake, my workaround solves rendering issue when it won't flush the final output, not the hooks issue.
See: Component Foo and its tests. - 1st test fails.

It also has an interesting outcome here:
When I write the rest of the template with v-else, I don't need to stub anymore !? :D
See: Component Fooo and its tests. - None fails.


For @tmorehouse issue, I can't reproduce it.
See: Component Bar and its tests. - None fails.

Thank you so much for those reproductions. I see. Yeah, we should provide more documentation on the removal of transition stub and workarounds. I'm going to close this issue after writing some docs up for both the transitions stub and async/sync test conversions.

@JessicaSachs I totally agree with you. But do mind one thing that my workaround is much simplified from the removed TransitionStub. It only helps the rendering. Hooks may not work correctly. ITMT, I will try to take a close look at the difference between using v-else and not to see if we can test transition without any workaround ;)

Was able to get the one failing test to pass in @hiendv 's repro with this:

  it.only('should not render qux', (done) => {
    const wrapper = mount(Foo)
    wrapper.setData({
      show: false
    })

    setTimeout(() => {
      console.log(wrapper.html())
      expect(wrapper.find('.v-leave').exists()).toBeFalsy()
      expect(wrapper.text()).not.toMatch(/qux/)
      done()
    }, 1000)
  })

So it is definitely a timing issue... although as pointed out, no amount of await nextTick solves this. I guess we need to investigate into how <transition> is implemented in core to look for a wait to solve this for testing.

@lmiller1990 Agree. A dive deep into <transition> implementation is also needed to solve the interesting issue with v-else.

@hiendv We are using v-if to trigger transitions, and we are also using functional re-usable transition components.

@tmorehouse It would be easier if you can set up a quick reproduction.

Deployed the latest docs with instructions on async tests and mocking transitions

Closing this issue. If necessary, please open additional issues with a reproduction to help us triage and fix them. Thanks!

Was this page helpful?
0 / 5 - 0 ratings