| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  | import Vue from 'vue' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-06 16:50:49 +08:00
										 |  |  | describe('Options lifecycle hooks', () => { | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |   let spy | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |     spy = vi.fn() | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 00:29:59 +08:00
										 |  |  |   describe('beforeCreate', () => { | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |     it('should allow modifying options', () => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         data: { | 
					
						
							|  |  |  |           a: 1 | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2016-06-28 00:29:59 +08:00
										 |  |  |         beforeCreate () { | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |           spy() | 
					
						
							|  |  |  |           expect(this.a).toBeUndefined() | 
					
						
							|  |  |  |           this.$options.computed = { | 
					
						
							|  |  |  |             b () { | 
					
						
							|  |  |  |               return this.a + 1 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |       expect(vm.b).toBe(2) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('created', () => { | 
					
						
							|  |  |  |     it('should have completed observation', () => { | 
					
						
							|  |  |  |       new Vue({ | 
					
						
							|  |  |  |         data: { | 
					
						
							|  |  |  |           a: 1 | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         created () { | 
					
						
							|  |  |  |           expect(this.a).toBe(1) | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('beforeMount', () => { | 
					
						
							|  |  |  |     it('should not have mounted', () => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							| 
									
										
										
										
											2016-11-25 01:53:13 +08:00
										 |  |  |         render () {}, | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |         beforeMount () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this._isMounted).toBe(false) | 
					
						
							|  |  |  |           expect(this.$el).toBeUndefined() // due to empty mount
 | 
					
						
							|  |  |  |           expect(this._vnode).toBeNull() | 
					
						
							|  |  |  |           expect(this._watcher).toBeNull() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.$mount() | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('mounted', () => { | 
					
						
							|  |  |  |     it('should have mounted', () => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: '<div></div>', | 
					
						
							|  |  |  |         mounted () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this._isMounted).toBe(true) | 
					
						
							|  |  |  |           expect(this.$el.tagName).toBe('DIV') | 
					
						
							|  |  |  |           expect(this._vnode.tag).toBe('div') | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.$mount() | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 11:03:21 +08:00
										 |  |  |     // #3898
 | 
					
						
							|  |  |  |     it('should call for manually mounted instance with parent', () => { | 
					
						
							| 
									
										
										
										
											2022-05-05 05:16:17 +08:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       const vm = new Vue() | 
					
						
							| 
									
										
										
										
											2016-10-11 11:03:21 +08:00
										 |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       new Vue({ | 
					
						
							|  |  |  |         parent, | 
					
						
							|  |  |  |         template: '<div></div>', | 
					
						
							|  |  |  |         mounted () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |     it('should mount child parent in correct order', () => { | 
					
						
							| 
									
										
										
										
											2022-05-02 04:37:05 +08:00
										 |  |  |       const calls: any[] = [] | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |       new Vue({ | 
					
						
							| 
									
										
										
										
											2017-02-07 08:18:50 +08:00
										 |  |  |         template: '<div><test></test></div>', | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |         mounted () { | 
					
						
							|  |  |  |           calls.push('parent') | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         components: { | 
					
						
							|  |  |  |           test: { | 
					
						
							| 
									
										
										
										
											2016-07-12 14:59:05 +08:00
										 |  |  |             template: '<nested></nested>', | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |             mounted () { | 
					
						
							| 
									
										
										
										
											2016-07-12 14:59:05 +08:00
										 |  |  |               expect(this.$el.parentNode).toBeTruthy() | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |               calls.push('child') | 
					
						
							| 
									
										
										
										
											2016-07-12 14:59:05 +08:00
										 |  |  |             }, | 
					
						
							|  |  |  |             components: { | 
					
						
							|  |  |  |               nested: { | 
					
						
							|  |  |  |                 template: '<div></div>', | 
					
						
							|  |  |  |                 mounted () { | 
					
						
							|  |  |  |                   expect(this.$el.parentNode).toBeTruthy() | 
					
						
							|  |  |  |                   calls.push('nested') | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							| 
									
										
										
										
											2016-07-12 14:59:05 +08:00
										 |  |  |       expect(calls).toEqual(['nested', 'child', 'parent']) | 
					
						
							| 
									
										
										
										
											2016-06-04 03:14:54 +08:00
										 |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('beforeUpdate', () => { | 
					
						
							|  |  |  |     it('should be called before update', done => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: '<div>{{ msg }}</div>', | 
					
						
							|  |  |  |         data: { msg: 'foo' }, | 
					
						
							|  |  |  |         beforeUpdate () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this.$el.textContent).toBe('foo') | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.msg = 'bar' | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() // should be async
 | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2018-03-24 07:03:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should be called before render and allow mutating state', done => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: '<div>{{ msg }}</div>', | 
					
						
							|  |  |  |         data: { msg: 'foo' }, | 
					
						
							|  |  |  |         beforeUpdate () { | 
					
						
							|  |  |  |           this.msg += '!' | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(vm.$el.textContent).toBe('foo') | 
					
						
							|  |  |  |       vm.msg = 'bar' | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(vm.$el.textContent).toBe('bar!') | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2018-12-12 00:31:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // #8076
 | 
					
						
							|  |  |  |     it('should not be called after destroy', done => { | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |       const beforeUpdate = vi.fn() | 
					
						
							|  |  |  |       const destroyed = vi.fn() | 
					
						
							| 
									
										
										
										
											2018-12-12 00:31:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       Vue.component('todo', { | 
					
						
							|  |  |  |         template: '<div>{{todo.done}}</div>', | 
					
						
							|  |  |  |         props: ['todo'], | 
					
						
							|  |  |  |         destroyed, | 
					
						
							|  |  |  |         beforeUpdate | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: `
 | 
					
						
							|  |  |  |           <div> | 
					
						
							|  |  |  |             <todo v-for="t in pendingTodos" :todo="t" :key="t.id"></todo> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         `,
 | 
					
						
							|  |  |  |         data () { | 
					
						
							|  |  |  |           return { | 
					
						
							|  |  |  |             todos: [{ id: 1, done: false }] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         computed: { | 
					
						
							|  |  |  |           pendingTodos () { | 
					
						
							|  |  |  |             return this.todos.filter(t => !t.done) | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       vm.todos[0].done = true | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(destroyed).toHaveBeenCalled() | 
					
						
							|  |  |  |         expect(beforeUpdate).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('updated', () => { | 
					
						
							|  |  |  |     it('should be called after update', done => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: '<div>{{ msg }}</div>', | 
					
						
							|  |  |  |         data: { msg: 'foo' }, | 
					
						
							|  |  |  |         updated () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this.$el.textContent).toBe('bar') | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.msg = 'bar' | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() // should be async
 | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(spy).toHaveBeenCalled() | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-12-30 05:19:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should be called after children are updated', done => { | 
					
						
							| 
									
										
										
										
											2022-05-02 04:37:05 +08:00
										 |  |  |       const calls: any[] = [] | 
					
						
							| 
									
										
										
										
											2016-12-30 05:19:44 +08:00
										 |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: '<div><test ref="child">{{ msg }}</test></div>', | 
					
						
							|  |  |  |         data: { msg: 'foo' }, | 
					
						
							|  |  |  |         components: { | 
					
						
							|  |  |  |           test: { | 
					
						
							|  |  |  |             template: `<div><slot></slot></div>`, | 
					
						
							|  |  |  |             updated () { | 
					
						
							|  |  |  |               expect(this.$el.textContent).toBe('bar') | 
					
						
							|  |  |  |               calls.push('child') | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         updated () { | 
					
						
							|  |  |  |           expect(this.$el.textContent).toBe('bar') | 
					
						
							|  |  |  |           calls.push('parent') | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(calls).toEqual([]) | 
					
						
							|  |  |  |       vm.msg = 'bar' | 
					
						
							|  |  |  |       expect(calls).toEqual([]) | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(calls).toEqual(['child', 'parent']) | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2018-10-25 01:24:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // #8076
 | 
					
						
							|  |  |  |     it('should not be called after destroy', done => { | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |       const updated = vi.fn() | 
					
						
							|  |  |  |       const destroyed = vi.fn() | 
					
						
							| 
									
										
										
										
											2018-10-25 01:24:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       Vue.component('todo', { | 
					
						
							|  |  |  |         template: '<div>{{todo.done}}</div>', | 
					
						
							|  |  |  |         props: ['todo'], | 
					
						
							|  |  |  |         destroyed, | 
					
						
							|  |  |  |         updated | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							|  |  |  |         template: `
 | 
					
						
							|  |  |  |           <div> | 
					
						
							|  |  |  |             <todo v-for="t in pendingTodos" :todo="t" :key="t.id"></todo> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         `,
 | 
					
						
							|  |  |  |         data () { | 
					
						
							|  |  |  |           return { | 
					
						
							|  |  |  |             todos: [{ id: 1, done: false }] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         computed: { | 
					
						
							|  |  |  |           pendingTodos () { | 
					
						
							|  |  |  |             return this.todos.filter(t => !t.done) | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       vm.todos[0].done = true | 
					
						
							|  |  |  |       waitForUpdate(() => { | 
					
						
							|  |  |  |         expect(destroyed).toHaveBeenCalled() | 
					
						
							|  |  |  |         expect(updated).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       }).then(done) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('beforeDestroy', () => { | 
					
						
							|  |  |  |     it('should be called before destroy', () => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							| 
									
										
										
										
											2016-11-25 01:53:13 +08:00
										 |  |  |         render () {}, | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |         beforeDestroy () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this._isBeingDestroyed).toBe(false) | 
					
						
							|  |  |  |           expect(this._isDestroyed).toBe(false) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.$destroy() | 
					
						
							|  |  |  |       vm.$destroy() | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |       expect(spy.mock.calls.length).toBe(1) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('destroyed', () => { | 
					
						
							|  |  |  |     it('should be called after destroy', () => { | 
					
						
							|  |  |  |       const vm = new Vue({ | 
					
						
							| 
									
										
										
										
											2016-11-25 01:53:13 +08:00
										 |  |  |         render () {}, | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |         destroyed () { | 
					
						
							|  |  |  |           spy() | 
					
						
							|  |  |  |           expect(this._isBeingDestroyed).toBe(true) | 
					
						
							|  |  |  |           expect(this._isDestroyed).toBe(true) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }).$mount() | 
					
						
							|  |  |  |       expect(spy).not.toHaveBeenCalled() | 
					
						
							|  |  |  |       vm.$destroy() | 
					
						
							|  |  |  |       vm.$destroy() | 
					
						
							|  |  |  |       expect(spy).toHaveBeenCalled() | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |       expect(spy.mock.calls.length).toBe(1) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2016-12-15 01:27:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should emit hook events', () => { | 
					
						
							| 
									
										
										
										
											2022-05-20 07:56:02 +08:00
										 |  |  |     const created = vi.fn() | 
					
						
							|  |  |  |     const mounted = vi.fn() | 
					
						
							|  |  |  |     const destroyed = vi.fn() | 
					
						
							| 
									
										
										
										
											2016-12-15 01:27:38 +08:00
										 |  |  |     const vm = new Vue({ | 
					
						
							|  |  |  |       render () {}, | 
					
						
							|  |  |  |       beforeCreate () { | 
					
						
							|  |  |  |         this.$on('hook:created', created) | 
					
						
							|  |  |  |         this.$on('hook:mounted', mounted) | 
					
						
							|  |  |  |         this.$on('hook:destroyed', destroyed) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(created).toHaveBeenCalled() | 
					
						
							|  |  |  |     expect(mounted).not.toHaveBeenCalled() | 
					
						
							|  |  |  |     expect(destroyed).not.toHaveBeenCalled() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vm.$mount() | 
					
						
							|  |  |  |     expect(mounted).toHaveBeenCalled() | 
					
						
							|  |  |  |     expect(destroyed).not.toHaveBeenCalled() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vm.$destroy() | 
					
						
							|  |  |  |     expect(destroyed).toHaveBeenCalled() | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2016-05-29 08:17:19 +08:00
										 |  |  | }) |