import Vue from 'vue' describe('Options directives', () => { it('basic usage', done => { const bindSpy = jasmine.createSpy('bind') const insertedSpy = jasmine.createSpy('inserted') const updateSpy = jasmine.createSpy('update') const componentUpdatedSpy = jasmine.createSpy('componentUpdated') const unbindSpy = jasmine.createSpy('unbind') const assertContext = (el, binding, vnode) => { expect(vnode.context).toBe(vm) expect(binding.arg).toBe('arg') expect(binding.modifiers).toEqual({ hello: true }) } const vm = new Vue({ template: '
{{ msg }}
', data: { msg: 'hi', a: 'foo', ok: true }, directives: { test: { bind (el, binding, vnode) { bindSpy() assertContext(el, binding, vnode) expect(binding.value).toBe('foo') expect(binding.expression).toBe('a') expect(binding.oldValue).toBeUndefined() expect(el.parentNode).toBeNull() }, inserted (el, binding, vnode) { insertedSpy() assertContext(el, binding, vnode) expect(binding.value).toBe('foo') expect(binding.expression).toBe('a') expect(binding.oldValue).toBeUndefined() expect(el.parentNode.className).toBe('hi') }, update (el, binding, vnode, oldVnode) { updateSpy() assertContext(el, binding, vnode) expect(el).toBe(vm.$el.children[0]) expect(oldVnode).not.toBe(vnode) expect(binding.expression).toBe('a') if (binding.value !== binding.oldValue) { expect(binding.value).toBe('bar') expect(binding.oldValue).toBe('foo') } }, componentUpdated (el, binding, vnode) { componentUpdatedSpy() assertContext(el, binding, vnode) }, unbind (el, binding, vnode) { unbindSpy() assertContext(el, binding, vnode) } } } }) vm.$mount() expect(bindSpy).toHaveBeenCalled() expect(insertedSpy).toHaveBeenCalled() expect(updateSpy).not.toHaveBeenCalled() expect(componentUpdatedSpy).not.toHaveBeenCalled() expect(unbindSpy).not.toHaveBeenCalled() vm.a = 'bar' waitForUpdate(() => { expect(updateSpy).toHaveBeenCalled() expect(componentUpdatedSpy).toHaveBeenCalled() expect(unbindSpy).not.toHaveBeenCalled() vm.msg = 'bye' }).then(() => { expect(componentUpdatedSpy.calls.count()).toBe(2) vm.ok = false }).then(() => { expect(unbindSpy).toHaveBeenCalled() }).then(done) }) it('function shorthand', done => { const spy = jasmine.createSpy('directive') const vm = new Vue({ template: '
', data: { a: 'foo' }, directives: { test (el, binding, vnode) { expect(vnode.context).toBe(vm) expect(binding.arg).toBe('arg') expect(binding.modifiers).toEqual({ hello: true }) spy(binding.value, binding.oldValue) } } }) vm.$mount() expect(spy).toHaveBeenCalledWith('foo', undefined) vm.a = 'bar' waitForUpdate(() => { expect(spy).toHaveBeenCalledWith('bar', 'foo') }).then(done) }) it('function shorthand (global)', done => { const spy = jasmine.createSpy('directive') Vue.directive('test', function (el, binding, vnode) { expect(vnode.context).toBe(vm) expect(binding.arg).toBe('arg') expect(binding.modifiers).toEqual({ hello: true }) spy(binding.value, binding.oldValue) }) const vm = new Vue({ template: '
', data: { a: 'foo' } }) vm.$mount() expect(spy).toHaveBeenCalledWith('foo', undefined) vm.a = 'bar' waitForUpdate(() => { expect(spy).toHaveBeenCalledWith('bar', 'foo') delete Vue.options.directives.test }).then(done) }) it('should teardown directives on old vnodes when new vnodes have none', done => { const vm = new Vue({ data: { ok: true }, template: `
a
b
`, directives: { test: { bind: el => { el.id = 'a' }, unbind: el => { el.id = '' } } } }).$mount() expect(vm.$el.children[0].id).toBe('a') vm.ok = false waitForUpdate(() => { expect(vm.$el.children[0].id).toBe('') expect(vm.$el.children[0].className).toBe('b') }).then(done) }) it('should properly handle same node with different directive sets', done => { const spies = {} const createSpy = name => (spies[name] = jasmine.createSpy(name)) const vm = new Vue({ data: { ok: true, val: 123 }, template: `
`, directives: { test: { bind: createSpy('bind1'), inserted: createSpy('inserted1'), update: createSpy('update1'), componentUpdated: createSpy('componentUpdated1'), unbind: createSpy('unbind1') }, test2: { bind: createSpy('bind2'), inserted: createSpy('inserted2'), update: createSpy('update2'), componentUpdated: createSpy('componentUpdated2'), unbind: createSpy('unbind2') } } }).$mount() expect(spies.bind1.calls.count()).toBe(2) expect(spies.inserted1.calls.count()).toBe(2) expect(spies.bind2.calls.count()).toBe(0) expect(spies.inserted2.calls.count()).toBe(0) vm.ok = false waitForUpdate(() => { // v-test with modifier should be updated expect(spies.update1.calls.count()).toBe(1) expect(spies.componentUpdated1.calls.count()).toBe(1) // v-test without modifier should be unbound expect(spies.unbind1.calls.count()).toBe(1) // v-test2 should be bound expect(spies.bind2.calls.count()).toBe(1) expect(spies.inserted2.calls.count()).toBe(1) vm.ok = true }).then(() => { // v-test without modifier should be bound again expect(spies.bind1.calls.count()).toBe(3) expect(spies.inserted1.calls.count()).toBe(3) // v-test2 should be unbound expect(spies.unbind2.calls.count()).toBe(1) // v-test with modifier should be updated again expect(spies.update1.calls.count()).toBe(2) expect(spies.componentUpdated1.calls.count()).toBe(2) vm.val = 234 }).then(() => { expect(spies.update1.calls.count()).toBe(4) expect(spies.componentUpdated1.calls.count()).toBe(4) }).then(done) }) it('warn non-existent', () => { new Vue({ template: '
' }).$mount() expect('Failed to resolve directive: test').toHaveBeenWarned() }) })