Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test Vue watcher that watches a computed property from VueX?

Tags:

Suppose I have the following component:

import { mapState } from 'vuex'; import externalDependency from '...';  export default {   name: 'Foo',   computed: {     ...mapState(['bar'])   },   watch: {     bar () {      externalDependency.doThing(this.bar);     }   } } 

When testing, I want to ensure that externalDependency.doThing() is called with bar (which comes from the vuex state) like so:

it('should call externalDependency.doThing with bar', () => {   const wrapper = mount(Foo);   const spy = jest.spyOn(externalDependency, 'doThing');    wrapper.setComputed({bar: 'baz'});    expect(spy).toHaveBeenCalledWith('baz'); }); 

Vue test-utils has a setComputed method which allows me to currently test it, but I keep getting warnings that setComputed will be removed soon, and I don't know how else this can be tested:

https://github.com/vuejs/vue-test-utils/issues/331

like image 951
yxu296 Avatar asked Mar 22 '18 14:03

yxu296


People also ask

Can you watch a computed property Vue?

Yes, you can setup watcher on computed property, see the fiddle.

What is the difference between watchers and computed property in Vuejs?

Computed props can react to changes in multiple props, whereas watched props can only watch one at a time. Computed props are cached, so they only recalculate when things change. Watched props are executed every time. Computed props are evaluated lazily, meaning they are only executed when they are needed to be used.

Are computed properties reactive Vue?

The Basics of Vue Reactivity Simply put, a computed property's dependencies are the reactive values that help the property that determine the value that is returned. If none of these change, then, again, the cached value will be returned. If no reactive dependency is changed, a computed property is not recalculated.

What are computed properties and watchers in Vue?

Get it here! Computed properties and watchers are reactive parts of the logic of Vue.js components. They both serve totally different purposes, one is synchronous and the other asynchronous, which makes them behave slightly different. In this article we'll go through testing them and see what different cases we can find on the way.

How do I add a Watcher to a Vue watch?

By convention, Vue will look it up in both properties and data state by using the watch function name, in this case inputValue, and since it will find it in data, it will add the watcher there. See that a watch function takes the new value as a first parameter, and the old one as the second.

How do I test a watch function?

We're using a spy on the console.log method, initializing before starting any test, and resetting its state after each of them, so that they start from a clean spy. To test a watch function, we just need to change the value of what's being watch, in this case the inputValue state. But there is something curious... let's start from last test:

What happens when you mutate reactive state in Vue?

} When you mutate reactive state, it may trigger both Vue component updates and watcher callbacks created by you. By default, user-created watcher callbacks are called before Vue component updates. This means if you attempt to access the DOM inside a watcher callback, the DOM will be in the state before Vue has applied any updates.


1 Answers

From you're trying to achieve

When testing, I want to ensure that externalDependency.doThing() is called with bar (which comes from the vuex state) like so:

(and this is indeed pure unit test approach), you can just force change of this watcher, which basically is a function. There's no need to track if watcher is changing in case of computed or data value change - let Vue handle it. So, to change a watcher in a mounted Vue instance, just call it like

wrapper.vm.$options.watch.bar.call(wrapper.vm) 

Where bar is name of your watcher. This way you will be able to test exact functionality that you're aiming to test.

Idea taken from this comment https://github.com/vuejs/vue-test-utils/issues/331#issuecomment-382037200, on a vue-test-utils issue, mentioned by you in a question.

like image 139
Andrew Miroshnichenko Avatar answered Oct 10 '22 08:10

Andrew Miroshnichenko