| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- import Vue from 'vue'
- describe('Options lifecycle hooks', () => {
- let spy
- beforeEach(() => {
- spy = vi.fn()
- })
- describe('beforeCreate', () => {
- it('should allow modifying options', () => {
- const vm = new Vue({
- data: {
- a: 1
- },
- beforeCreate() {
- 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({
- render() {},
- 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()
- })
- // #3898
- it('should call for manually mounted instance with parent', () => {
- const parent = new Vue()
- expect(spy).not.toHaveBeenCalled()
- new Vue({
- parent,
- template: '<div></div>',
- mounted() {
- spy()
- }
- }).$mount()
- expect(spy).toHaveBeenCalled()
- })
- it('should mount child parent in correct order', () => {
- const calls: any[] = []
- new Vue({
- template: '<div><test></test></div>',
- mounted() {
- calls.push('parent')
- },
- components: {
- test: {
- template: '<nested></nested>',
- mounted() {
- expect(this.$el.parentNode).toBeTruthy()
- calls.push('child')
- },
- components: {
- nested: {
- template: '<div></div>',
- mounted() {
- expect(this.$el.parentNode).toBeTruthy()
- calls.push('nested')
- }
- }
- }
- }
- }
- }).$mount()
- expect(calls).toEqual(['nested', 'child', 'parent'])
- })
- })
- 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)
- })
- 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)
- })
- // #8076
- it('should not be called after destroy', done => {
- const beforeUpdate = vi.fn()
- const destroyed = vi.fn()
- 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)
- })
- })
- 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)
- })
- it('should be called after children are updated', done => {
- const calls: any[] = []
- 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)
- })
- // #8076
- it('should not be called after destroy', done => {
- const updated = vi.fn()
- const destroyed = vi.fn()
- 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)
- })
- })
- describe('beforeDestroy', () => {
- it('should be called before destroy', () => {
- const vm = new Vue({
- render() {},
- beforeDestroy() {
- spy()
- expect(this._isBeingDestroyed).toBe(false)
- expect(this._isDestroyed).toBe(false)
- }
- }).$mount()
- expect(spy).not.toHaveBeenCalled()
- vm.$destroy()
- vm.$destroy()
- expect(spy).toHaveBeenCalled()
- expect(spy.mock.calls.length).toBe(1)
- })
- })
- describe('destroyed', () => {
- it('should be called after destroy', () => {
- const vm = new Vue({
- render() {},
- destroyed() {
- spy()
- expect(this._isBeingDestroyed).toBe(true)
- expect(this._isDestroyed).toBe(true)
- }
- }).$mount()
- expect(spy).not.toHaveBeenCalled()
- vm.$destroy()
- vm.$destroy()
- expect(spy).toHaveBeenCalled()
- expect(spy.mock.calls.length).toBe(1)
- })
- })
- it('should emit hook events', () => {
- const created = vi.fn()
- const mounted = vi.fn()
- const destroyed = vi.fn()
- 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()
- })
- })
|