diff --git a/packages/test-utils/src/order-watchers.js b/packages/test-utils/src/order-watchers.js new file mode 100644 index 000000000..371b11014 --- /dev/null +++ b/packages/test-utils/src/order-watchers.js @@ -0,0 +1,33 @@ +let i = 0 + +function orderDeps (watcher) { + watcher.deps.forEach(dep => { + if (dep._sortedId === i) { + return + } + dep._sortedId = i + dep.subs.forEach(orderDeps) + dep.subs = dep.subs.sort((a, b) => a.id - b.id) + }) +} + +function orderVmWatchers (vm) { + if (vm._watchers) { + vm._watchers.forEach(orderDeps) + } + + if (vm._computedWatchers) { + Object.keys(vm._computedWatchers).forEach((computedWatcher) => { + orderDeps(vm._computedWatchers[computedWatcher]) + }) + } + + orderDeps(vm._watcher) + + vm.$children.forEach(orderVmWatchers) +} + +export function orderWatchers (vm) { + orderVmWatchers(vm) + i++ +} diff --git a/packages/test-utils/src/set-watchers-to-sync.js b/packages/test-utils/src/set-watchers-to-sync.js index a2c52cce3..93fd85d7a 100644 --- a/packages/test-utils/src/set-watchers-to-sync.js +++ b/packages/test-utils/src/set-watchers-to-sync.js @@ -1,5 +1,4 @@ function setDepsSync (dep) { - dep.subs = dep.subs.sort((a, b) => a.id - b.id) dep.subs.forEach(setWatcherSync) } diff --git a/packages/test-utils/src/vue-wrapper.js b/packages/test-utils/src/vue-wrapper.js index e85613e57..6836586c2 100644 --- a/packages/test-utils/src/vue-wrapper.js +++ b/packages/test-utils/src/vue-wrapper.js @@ -2,6 +2,7 @@ import Wrapper from './wrapper' import { setWatchersToSync } from './set-watchers-to-sync' +import { orderWatchers } from './order-watchers' export default class VueWrapper extends Wrapper implements BaseWrapper { constructor (vm: Component, options: WrapperOptions) { @@ -20,6 +21,7 @@ export default class VueWrapper extends Wrapper implements BaseWrapper { this.vm = vm if (options.sync) { setWatchersToSync(vm) + orderWatchers(vm) } this.isVueComponent = true this.isFunctionalComponent = vm.$options._isFunctionalContainer diff --git a/packages/test-utils/src/wrapper.js b/packages/test-utils/src/wrapper.js index fe0c32210..790904ce3 100644 --- a/packages/test-utils/src/wrapper.js +++ b/packages/test-utils/src/wrapper.js @@ -21,6 +21,9 @@ import { } from 'shared/util' import findAll from './find' import createWrapper from './create-wrapper' +import { + orderWatchers +} from './order-watchers' export default class Wrapper implements BaseWrapper { vnode: VNode | null; @@ -621,6 +624,9 @@ export default class Wrapper implements BaseWrapper { } this.element.dispatchEvent(eventObject) + if (this.vnode) { + orderWatchers(this.vm || this.vnode.context.$root) + } } update () { diff --git a/test/specs/mounting-options/snyc.spec.js b/test/specs/mounting-options/snyc.spec.js index 90f1da847..1984c7ef8 100644 --- a/test/specs/mounting-options/snyc.spec.js +++ b/test/specs/mounting-options/snyc.spec.js @@ -31,6 +31,63 @@ describeWithShallowAndMount('options.sync', (mountingMethod) => { expect(wrapper.text()).to.equal('world') }) + it('handles methods that update watchers', () => { + const TestComponent = { + template: ` +
+
+
+
data.text: {{ text }}
+
+ +
+
computed.text: {{ computedText }}
+
+
+
+ `, + data () { + return { + open: false, + text: '', + basket: [] + } + }, + computed: { + computedText () { + return this.text + } + }, + created () { + window.addEventListener('click', this.clickHandler) + }, + destroyed () { + window.removeEventListener('click', this.clickHandler) + }, + watch: { + text () { + this.basket.push(this.computedText) + } + }, + methods: { + clickHandler () { + this.open = !this.open + } + } + } + + const wrapper = mountingMethod(TestComponent, { + attachToDocument: true + }) + wrapper.trigger('click') + expect(wrapper.vm.text).to.equal('') + expect(wrapper.vm.basket.length).to.equal(0) + wrapper.setData({ text: 'foo' }) + expect(wrapper.vm.text).to.equal('foo') + expect(wrapper.vm.computedText).to.equal('foo') + expect(wrapper.vm.basket[0]).to.equal('foo') + }) + it('does not set watchers to sync if set to false', (done) => { const TestComponent = { template: '
{{someData}}
',