You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

180 lines
3.6 KiB

import Vue from 'vue'
import {
MAX_UPDATE_COUNT,
queueWatcher as _queueWatcher
} from 'core/observer/scheduler'
function queueWatcher (watcher) {
watcher.vm = {} // mock vm
_queueWatcher(watcher)
}
describe('Scheduler', () => {
let spy
beforeEach(() => {
spy = jasmine.createSpy('scheduler')
})
it('queueWatcher', done => {
queueWatcher({
run: spy
})
waitForUpdate(() => {
expect(spy.calls.count()).toBe(1)
}).then(done)
})
it('dedup', done => {
queueWatcher({
id: 1,
run: spy
})
queueWatcher({
id: 1,
run: spy
})
waitForUpdate(() => {
expect(spy.calls.count()).toBe(1)
}).then(done)
})
it('allow duplicate when flushing', done => {
const job = {
id: 1,
run: spy
}
queueWatcher(job)
queueWatcher({
id: 2,
run () { queueWatcher(job) }
})
waitForUpdate(() => {
expect(spy.calls.count()).toBe(2)
}).then(done)
})
it('call user watchers before component re-render', done => {
const calls = []
const vm = new Vue({
data: {
a: 1
},
template: '<div>{{ a }}</div>',
watch: {
a () { calls.push(1) }
},
beforeUpdate () {
calls.push(2)
}
}).$mount()
vm.a = 2
waitForUpdate(() => {
expect(calls).toEqual([1, 2])
}).then(done)
})
it('call user watcher triggered by component re-render immediately', done => {
// this happens when a component re-render updates the props of a child
const calls = []
const vm = new Vue({
data: {
a: 1
},
watch: {
a () {
calls.push(1)
}
},
beforeUpdate () {
calls.push(2)
},
template: '<div><test :a="a"></test></div>',
components: {
test: {
props: ['a'],
template: '<div>{{ a }}</div>',
watch: {
a () {
calls.push(3)
}
},
beforeUpdate () {
calls.push(4)
}
}
}
}).$mount()
vm.a = 2
waitForUpdate(() => {
expect(calls).toEqual([1, 2, 3, 4])
}).then(done)
})
it('warn against infinite update loops', function (done) {
let count = 0
const job = {
id: 1,
run () {
count++
queueWatcher(job)
}
}
queueWatcher(job)
waitForUpdate(() => {
expect(count).toBe(MAX_UPDATE_COUNT + 1)
expect('infinite update loop').toHaveBeenWarned()
}).then(done)
})
it('should call newly pushed watcher after current watcher is done', done => {
const callOrder = []
queueWatcher({
id: 1,
user: true,
run () {
callOrder.push(1)
queueWatcher({
id: 2,
run () {
callOrder.push(3)
}
})
callOrder.push(2)
}
})
waitForUpdate(() => {
expect(callOrder).toEqual([1, 2, 3])
}).then(done)
})
// GitHub issue #5191
it('emit should work when updated hook called', done => {
const el = document.createElement('div')
const vm = new Vue({
template: `<div><child @change="bar" :foo="foo"></child></div>`,
data: {
foo: 0
},
methods: {
bar: spy
},
components: {
child: {
template: `<div>{{foo}}</div>`,
props: ['foo'],
updated () {
this.$emit('change')
}
}
}
}).$mount(el)
vm.$nextTick(() => {
vm.foo = 1
vm.$nextTick(() => {
expect(vm.$el.innerHTML).toBe('<div>1</div>')
expect(spy).toHaveBeenCalled()
done()
})
})
})
})