From fa669fab04c9a36ac2690e79186bb04c426e8ab8 Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 21 Jul 2020 23:10:51 -0400 Subject: [PATCH] fix(setprops): allowed for setProps to be synced with nextTick intervals setProps in certain cases was being blown away by nextTick intervals. If the property is not up to date, setProps will be called again to sync the changes. fix #1419 --- packages/test-utils/src/wrapper.js | 12 ++++- test/specs/wrapper/setProps.spec.js | 75 +++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index 6ea73b2cf..1f6bfe8c7 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -711,7 +711,17 @@ export default class Wrapper implements BaseWrapper { // $FlowIgnore : Problem with possibly null this.vm this.vm.$forceUpdate() - return nextTick() + return new Promise((resolve, reject) => { + nextTick().then(() => { + const isUpdated = Object.keys(data).some(key => { + return ( + // $FlowIgnore : Problem with possibly null this.vm + this.vm[key] === data[key] || this.vm.$attrs[key] === data[key] + ) + }) + return !isUpdated ? this.setProps(data).then(resolve()) : resolve() + }) + }) } catch (err) { throw err } finally { diff --git a/test/specs/wrapper/setProps.spec.js b/test/specs/wrapper/setProps.spec.js index 635ffae66..ebd54cc17 100644 --- a/test/specs/wrapper/setProps.spec.js +++ b/test/specs/wrapper/setProps.spec.js @@ -187,6 +187,81 @@ describeWithShallowAndMount('setProps', mountingMethod => { await wrapper.setProps({ prop1 }) expect(wrapper.vm.prop2).to.equal(prop1) }) + + it('invokes watchers with immediate set to "true"', async () => { + const callback = sinon.spy() + const TestComponent = { + template: '
', + props: ['propA'], + mounted() { + this.$watch( + 'propA', + function() { + callback() + }, + { immediate: true } + ) + } + } + const wrapper = mountingMethod(TestComponent, { + propsData: { propA: 'none' } + }) + + expect(callback.calledOnce) + callback.resetHistory() + + await wrapper.setProps({ propA: 'value' }) + expect(wrapper.props().propA).to.equal('value') + expect(callback.calledOnce) + }) + + it('invokes watchers with immediate set to "true" with deep objects', async () => { + const callback = sinon.spy() + const TestComponent = { + template: '
', + props: ['propA'], + mounted() { + this.$watch( + 'propA', + function() { + callback() + }, + { immediate: true } + ) + } + } + const wrapper = mountingMethod(TestComponent, { + propsData: { + propA: { + key: { + nestedKey: 'value' + }, + key2: 'value2' + } + } + }) + + expect(callback.calledOnce) + callback.resetHistory() + + await wrapper.setProps({ + propA: { + key: { + nestedKey: 'newValue', + anotherNestedKey: 'value' + }, + key2: 'value2' + } + }) + expect(wrapper.props().propA).to.deep.equal({ + key: { + nestedKey: 'newValue', + anotherNestedKey: 'value' + }, + key2: 'value2' + }) + expect(callback.calledOnce) + }) }) it('props and setProps should return the same reference when called with same object', () => {