vuejs / vue-test-utils

Component Test Utils for Vue 2
https://vue-test-utils.vuejs.org
MIT License
3.57k stars 668 forks source link

"update:prop" doesn't mutate array prop #1497

Open ndabAP opened 4 years ago

ndabAP commented 4 years ago

Version

1.0.0-beta.32

Reproduction link

https://github.com/ndabAP/vue-test-utils-props-update-issue

Steps to reproduce

vue-test-utils-props-update-issue

  1. Run npm i
  2. npm run serve
  3. See [1, 2]
  4. npm run test
  5. See [1] instead of [1, 2]

Mutation happens here:

https://github.com/ndabAP/vue-test-utils-props-update-issue/blob/master/src/components/Array.vue#L18

Test logging happens here:

https://github.com/ndabAP/vue-test-utils-props-update-issue/blob/master/tests/unit/example.spec.js#L13

What is expected?

See [1, 2] at step 5

What is actually happening?

See [1]

dobromir-hristov commented 4 years ago

No it should not. That would happen if the parent component catches that change and updates accordingly. Test if the event is emitted.

ndabAP commented 4 years ago

The problem is, the event is emitted but that's not important in my case. I need the array to mutate so the childs DOM updates, which is not happening.

Also it behaves correctly when not using the test suite. The "sync" modifier makes sure it updates the mother value.

dobromir-hristov commented 4 years ago

That is not how you unit test a component. Mount your component in a parent element and test that, if that is what you want. But testing if the event is called is the proper way.

ndabAP commented 4 years ago

Testing for the event wouldn't be enough in my case. I'm working on a Vue.js terminal emulator (here) and users can push components as STDOUT/STDERR. The history of the terminal is an array. When a component is pushed to history, the users component is rendered and gets additional computed properties programmatically (here). I'd need to test for this properties to be correct after they have been pushed to the history (here).

I'd expect from this framework that I can test the Vue.js API fully (feature parity).

dobromir-hristov commented 4 years ago

You need to test how 2 components interact, you are testing one. As I said wrap your component in a another and test accordingly.

lmiller1990 commented 4 years ago

If you render <Array /> inside of another component, this should work. Eg:

Foo.vue

<div> 
  <Array />
</div>

Test:

const wrapper = mount(Foo)

// interact with said component
// assert against DOM

This won't work if Array is directly mounted, since there is no parent element to listen for the event (Array is at the top). I understand your use case, I might play around but I don't think this is something that can be fixed based on the current design. The work around would be wrapping your component (like your real app does).

That said, if you want to test that X is rendered when <Array> receives Y props, can you just use the propsData mounting option? What's the need to test that mutation occurs? You can be confident that mutations triggers a re-render - Vue has you covered.

ndabAP commented 4 years ago

Hey @lmiller1990,

thanks a lot for your help. I tried your approach but still don't see the array mutated:

  1. I created a wrapper:

https://github.com/ndabAP/vue-test-utils-props-update-issue/blob/test/wrap-test-component/tests/unit/ArrayWrapper.vue

  1. I check if the wrapped component prop is mutated:

https://github.com/ndabAP/vue-test-utils-props-update-issue/blob/test/wrap-test-component/tests/unit/example.spec.js#L11

That said, if you want to test that X is rendered when receives Y props, can you just use the propsData mounting option? What's the need to test that mutation occurs? You can be confident that mutations triggers a re-render - Vue has you covered.

I used propsData before but in my case I extend the users given component (inside the array) about computed properties which I would like to test for.

lmiller1990 commented 4 years ago

That should work. I will look into this.

Btw, can you share where this component in your cli app?

PS in Vue 3 .vm is not public (this is a Vue core thing, a lot less stuff is exposed outside the component). So that style of test (most likely) won't work. I am writing docs on how to handle these cases for those who wish to upgrade.

edit: we now expose vm in VTU next. :D