From a313af286a4a162a168a6304528e1855541008f4 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 2 Sep 2019 18:42:01 +0300 Subject: [PATCH 1/2] chore: Add async test with immediate watcher --- .../component-with-watch-immediate.vue | 22 +++++++++++++++++++ test/specs/config.spec.js | 4 +--- test/specs/wrapper/setProps.spec.js | 12 ++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test/resources/components/component-with-watch-immediate.vue diff --git a/test/resources/components/component-with-watch-immediate.vue b/test/resources/components/component-with-watch-immediate.vue new file mode 100644 index 000000000..a660b9865 --- /dev/null +++ b/test/resources/components/component-with-watch-immediate.vue @@ -0,0 +1,22 @@ + + diff --git a/test/specs/config.spec.js b/test/specs/config.spec.js index dc078413d..f17b23def 100644 --- a/test/specs/config.spec.js +++ b/test/specs/config.spec.js @@ -104,9 +104,7 @@ describeWithShallowAndMount('config', mountingMethod => { localVue }) expect(wrapper.vm.prop1).to.equal('example') - wrapper.setProps({ - prop1: 'new value' - }) + wrapper.vm.prop1 = 'new value' expect(console.error).calledWith(sandbox.match('[Vue warn]')) }) }) diff --git a/test/specs/wrapper/setProps.spec.js b/test/specs/wrapper/setProps.spec.js index de74807dd..29b38c905 100644 --- a/test/specs/wrapper/setProps.spec.js +++ b/test/specs/wrapper/setProps.spec.js @@ -1,6 +1,7 @@ import { compileToFunctions } from 'vue-template-compiler' import ComponentWithProps from '~resources/components/component-with-props.vue' import ComponentWithWatch from '~resources/components/component-with-watch.vue' +import ComponentWithWatchImmediate from '~resources/components/component-with-watch-immediate.vue' import { describeWithShallowAndMount, vueVersion } from '~resources/utils' import { itDoNotRunIf } from 'conditional-specs' import Vue from 'vue' @@ -244,6 +245,17 @@ describeWithShallowAndMount('setProps', mountingMethod => { expect(wrapper.vm.propA).to.equal('value') }) + it('correctly sets props in async mode when component has immediate watchers', async () => { + const wrapper = mountingMethod(ComponentWithWatchImmediate, { + sync: false + }) + + const prop1 = 'testest' + wrapper.setProps({ prop1 }) + await Vue.nextTick() + expect(wrapper.vm.prop1).to.equal(prop1) + }) + it('throws an error if node is not a Vue instance', () => { const message = 'wrapper.setProps() can only be called on a Vue instance' const compiled = compileToFunctions('

') From ec99da1d6bc1119cd3a33a360ef4a5e63ccd47a8 Mon Sep 17 00:00:00 2001 From: Illya Klymov Date: Mon, 2 Sep 2019 18:53:40 +0300 Subject: [PATCH 2/2] fix: add support for proper props update in async mode Since we're already wrapping a component into a parent one we can get rid of explicitly setting props on component, instead modifying them being passed from parent component instead --- packages/create-instance/create-instance.js | 12 +++++-- packages/test-utils/src/wrapper.js | 35 ++++++--------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 562c1f852..648703afe 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -11,7 +11,7 @@ import createScopedSlots from './create-scoped-slots' import { createStubsFromStubsObject } from './create-component-stubs' import { patchCreateElement } from './patch-create-element' -function createContext(options, scopedSlots) { +function createContext(options, scopedSlots, currentProps) { const on = { ...(options.context && options.context.on), ...options.listeners @@ -21,7 +21,7 @@ function createContext(options, scopedSlots) { ...options.attrs, // pass as attrs so that inheritAttrs works correctly // propsData should take precedence over attrs - ...options.propsData + ...currentProps }, ...(options.context || {}), on, @@ -84,10 +84,16 @@ export default function createInstance( parentComponentOptions.provide = options.provide parentComponentOptions.$_doNotStubChildren = true parentComponentOptions._isFunctionalContainer = componentOptions.functional + const originalDataFn = parentComponentOptions.data + parentComponentOptions.data = function() { + const originalData = originalDataFn ? originalDataFn() : {} + originalData.vueTestUtils_childProps = { ...options.propsData } + return originalData + } parentComponentOptions.render = function(h) { return h( Constructor, - createContext(options, scopedSlots), + createContext(options, scopedSlots, this.vueTestUtils_childProps), createChildren(this, h, options) ) } diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 956227a8b..3549ba6fc 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -1,10 +1,7 @@ // @flow - -import Vue from 'vue' import pretty from 'pretty' import getSelector from './get-selector' import { REF_SELECTOR, FUNCTIONAL_OPTIONS, VUE_VERSION } from 'shared/consts' -import config from './config' import WrapperArray from './wrapper-array' import ErrorWrapper from './error-wrapper' import { throwError, getCheckedEvent, isPhantomJS } from 'shared/util' @@ -455,8 +452,6 @@ export default class Wrapper implements BaseWrapper { * Sets vm props */ setProps(data: Object): void { - const originalConfig = Vue.config.silent - Vue.config.silent = config.silent if (this.isFunctionalComponent) { throwError( `wrapper.setProps() cannot be called on a functional component` @@ -480,38 +475,26 @@ export default class Wrapper implements BaseWrapper { ) } if ( - !this.vm || - !this.vm.$options._propKeys || - !this.vm.$options._propKeys.some(prop => prop === key) + VUE_VERSION <= 2.3 && + // $FlowIgnore : Problem with possibly null this.vm + (!this.vm.$options._propKeys || + !this.vm.$options._propKeys.some(prop => prop === key)) ) { - if (VUE_VERSION > 2.3) { - // $FlowIgnore : Problem with possibly null this.vm - this.vm.$attrs[key] = data[key] - return - } throwError( `wrapper.setProps() called with ${key} property which ` + `is not defined on the component` ) } - if (this.vm && this.vm._props) { - // Set actual props value - this.vm._props[key] = data[key] - // $FlowIgnore : Problem with possibly null this.vm - this.vm[key] = data[key] - } else { - // $FlowIgnore : Problem with possibly null this.vm.$options - this.vm.$options.propsData[key] = data[key] - // $FlowIgnore : Problem with possibly null this.vm - this.vm[key] = data[key] - // $FlowIgnore : Need to call this twice to fix watcher bug in 2.0.x - this.vm[key] = data[key] + if (this.vm && this.vm.$parent) { + this.vm.$parent.vueTestUtils_childProps[key] = data[key] } }) // $FlowIgnore : Problem with possibly null this.vm this.vm.$forceUpdate() - Vue.config.silent = originalConfig + // We need to explicitly trigger parent watcher to support sync scenarios + // $FlowIgnore : Problem with possibly null this.vm + this.vm.$parent._watcher.run() } /** pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy