vue-test-utils: setData does not force a re-render of the component when using v-model, data(), and a computed property
Version
1.0.0-beta.13
Reproduction link
https://github.com/s-robertson/vtu-setdata
Steps to reproduce
Create a new Vue component with the following criteria:
- Have
data()return an object containing an empty string, e.g.msg - Have a computed property that returns a boolean depending on if
msgis empty or not. E.g.hasMsg - Have an
<input>in the component template that usesv-model, bound tomsg - Have an element, such as an
<h1>in the component template that usesv-if, bound tohasMsg. This element must come AFTER the<input>in the template
Now write a unit test that:
- Mounts the component via
shallow() - Calls
setDataand setsmsgto a non-empty string - Checks to see if the template contains the
<h1>
Finally, run the unit test.
What is expected?
Calling setData will cause the component to re-render, making hasMsg be true and the test will pass.
What is actually happening?
Calling setData does not cause the component to re-render. The unit test cannot find the <h1> element and fails:
FAIL tests/unit/HelloWorld.spec.js
HelloWorld.vue
✕ renders props.msg when passed (36ms)
● HelloWorld.vue › renders props.msg when passed
expect(received).toBe(expected) // Object.is equality
Expected value to be:
true
Received:
false
9 | wrapper.setData({ msg });
10 |
> 11 | expect(wrapper.contains('h1')).toBe(true);
12 | })
13 | });
14 |
at Object.<anonymous> (tests/unit/HelloWorld.spec.js:11:36)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.062s
Ran all test suites.
ERROR jest exited with code 1.
error Command failed with exit code 1.
What’s interesting is that the order of the <input> and <h1> in the template matters. If the <h1> comes before the <input> the test will also pass.
You can also get the test to pass by forcefully updating the component via wrapper.vm.$forceUpdate(); after you’ve called setData.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (6 by maintainers)
@onomojo @rafaoliverce what do your tests look like? Are you using
await wrapper.vm.$nextTick()in your tests? There was a large breaking change in v30 to remove sync mode. This requires you to await for Vue to finish the next event loop after each change that will affect the DOM.Here are the current docs on it https://vue-test-utils.vuejs.org/guides/testing-async-components.html#updates-applied-by-vue
I’ve found that sometimes I have to use an
asyncfunction and callawaitonsetDataandsetProps@narenderv7 Have you tried setting
syncto false and usingVue.nextTick?@eddyerburgh
version:
@vue/test-utils": "^1.0.0-beta.16"I have a
v-ifpointing to adataproperty callederrors.recordTypeon an element with the attributedata-test-id="record-type-error"this fails…
this does not…
Seems to not be fixed yet, unless I’m doing something wrong.
Yes, probably that’s the cause of the problems. Thanks @JessicaSachs !
This seems to have regressed starting with 1.0.0-beta.30 and still broken in 1.0.0-beta.31. 1.0.0-beta.29 seems to work fine for me though.
@maoberlehner Similarly I’m using
v-if = "show"property, Initially it was set tofalseand I’m making it astruein a method. I’ve tried set the{show = true}using (setData) and called the particular method But got a_isDestroyedofundefined. please see the code below.While running this test got following error ~~
Test.test.js › Methods › should call toggleShow
(node_modules/vue/dist/vue.runtime.common.js:1012:11) at VueComponent.proxySetter [as show] (node_modules/vue/dist/vue.runtime.common.js:3298:26) at VueComponent.set [as $set] (node_modules/vue/dist/vue.runtime.common.js:1034:17) at node_modules/@vue/test-utils/dist/vue-test-utils.js:1162:10 at Array.forEach (<anonymous>) at recursivelySetData (node_modules/@vue/test-utils/dist/vue-test-utils.js:1155:21) at VueWrapper.setData (node_modules/@vue/test-utils/dist/vue-test-utils.js:1654:3) at Object.setData (test/unit/views/tdi/HFE.test.js:59:15)
I believe this has been fixed in the dev branch. The test case you provided passes.