| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- import Vue from 'vue'
- import Watcher from 'core/observer/watcher'
- describe('Watcher', () => {
- let vm, spy
- beforeEach(() => {
- vm = new Vue({
- template: '<div></div>',
- data: {
- a: 1,
- b: {
- c: 2,
- d: 4
- },
- c: 'c',
- msg: 'yo'
- }
- }).$mount()
- spy = vi.fn()
- })
- it('path', done => {
- const watcher = new Watcher(vm, 'b.c', spy)
- expect(watcher.value).toBe(2)
- vm.b.c = 3
- waitForUpdate(() => {
- expect(watcher.value).toBe(3)
- expect(spy).toHaveBeenCalledWith(3, 2)
- vm.b = { c: 4 } // swapping the object
- })
- .then(() => {
- expect(watcher.value).toBe(4)
- expect(spy).toHaveBeenCalledWith(4, 3)
- })
- .then(done)
- })
- it('non-existent path, set later', done => {
- const watcher1 = new Watcher(vm, 'b.e', spy)
- expect(watcher1.value).toBeUndefined()
- // check $add should not affect isolated children
- const child2 = new Vue({ parent: vm })
- const watcher2 = new Watcher(child2, 'b.e', spy)
- expect(watcher2.value).toBeUndefined()
- Vue.set(vm.b, 'e', 123)
- waitForUpdate(() => {
- expect(watcher1.value).toBe(123)
- expect(watcher2.value).toBeUndefined()
- expect(spy.mock.calls.length).toBe(1)
- expect(spy).toHaveBeenCalledWith(123, undefined)
- }).then(done)
- })
- it('delete', done => {
- const watcher = new Watcher(vm, 'b.c', spy)
- expect(watcher.value).toBe(2)
- Vue.delete(vm.b, 'c')
- waitForUpdate(() => {
- expect(watcher.value).toBeUndefined()
- expect(spy).toHaveBeenCalledWith(undefined, 2)
- }).then(done)
- })
- it('path containing $data', done => {
- const watcher = new Watcher(vm, '$data.b.c', spy)
- expect(watcher.value).toBe(2)
- vm.b = { c: 3 }
- waitForUpdate(() => {
- expect(watcher.value).toBe(3)
- expect(spy).toHaveBeenCalledWith(3, 2)
- vm.$data.b.c = 4
- })
- .then(() => {
- expect(watcher.value).toBe(4)
- expect(spy).toHaveBeenCalledWith(4, 3)
- })
- .then(done)
- })
- it('deep watch', done => {
- let oldB
- new Watcher(vm, 'b', spy, {
- deep: true
- })
- vm.b.c = { d: 4 }
- waitForUpdate(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
- oldB = vm.b
- vm.b = { c: [{ a: 1 }] }
- })
- .then(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, oldB)
- expect(spy.mock.calls.length).toBe(2)
- vm.b.c[0].a = 2
- })
- .then(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
- expect(spy.mock.calls.length).toBe(3)
- })
- .then(done)
- })
- it('deep watch $data', done => {
- new Watcher(vm, '$data', spy, {
- deep: true
- })
- vm.b.c = 3
- waitForUpdate(() => {
- expect(spy).toHaveBeenCalledWith(vm.$data, vm.$data)
- }).then(done)
- })
- it('deep watch with circular references', done => {
- new Watcher(vm, 'b', spy, {
- deep: true
- })
- Vue.set(vm.b, '_', vm.b)
- waitForUpdate(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
- expect(spy.mock.calls.length).toBe(1)
- vm.b._.c = 1
- })
- .then(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
- expect(spy.mock.calls.length).toBe(2)
- })
- .then(done)
- })
- it('fire change for prop addition/deletion in non-deep mode', done => {
- new Watcher(vm, 'b', spy)
- Vue.set(vm.b, 'e', 123)
- waitForUpdate(() => {
- expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
- expect(spy.mock.calls.length).toBe(1)
- Vue.delete(vm.b, 'e')
- })
- .then(() => {
- expect(spy.mock.calls.length).toBe(2)
- })
- .then(done)
- })
- it('watch function', done => {
- const watcher = new Watcher(
- vm,
- function () {
- return this.a + this.b.d
- },
- spy
- )
- expect(watcher.value).toBe(5)
- vm.a = 2
- waitForUpdate(() => {
- expect(spy).toHaveBeenCalledWith(6, 5)
- vm.b = { d: 2 }
- })
- .then(() => {
- expect(spy).toHaveBeenCalledWith(4, 6)
- })
- .then(done)
- })
- it('lazy mode', done => {
- const watcher = new Watcher(
- vm,
- function () {
- return this.a + this.b.d
- },
- null,
- { lazy: true }
- )
- expect(watcher.lazy).toBe(true)
- expect(watcher.value).toBeUndefined()
- expect(watcher.dirty).toBe(true)
- watcher.evaluate()
- expect(watcher.value).toBe(5)
- expect(watcher.dirty).toBe(false)
- vm.a = 2
- waitForUpdate(() => {
- expect(watcher.value).toBe(5)
- expect(watcher.dirty).toBe(true)
- watcher.evaluate()
- expect(watcher.value).toBe(6)
- expect(watcher.dirty).toBe(false)
- }).then(done)
- })
- it('teardown', done => {
- const watcher = new Watcher(vm, 'b.c', spy)
- watcher.teardown()
- vm.b.c = 3
- waitForUpdate(() => {
- expect(watcher.active).toBe(false)
- expect(spy).not.toHaveBeenCalled()
- }).then(done)
- })
- it('warn not support path', () => {
- new Watcher(vm, 'd.e + c', spy)
- expect('Failed watching path:').toHaveBeenWarned()
- })
- })
|