UNPKG

bootstrap-vue

Version:

With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extens

246 lines (216 loc) 7.58 kB
import { isVue3 } from '../vue' import { mount } from '@vue/test-utils' import { listenersMixin } from './listeners' // Note: The following tests indirectly test `utils/cache` describe('mixins > listeners', () => { it('works', async () => { const BTest = { compatConfig: { MODE: 3, RENDER_FUNCTION: 'suppress-warning', INSTANCE_LISTENERS: 'suppress-warning' }, name: 'BTest', mixins: [listenersMixin], inheritAttrs: false, render(h) { return h('button', { on: this.bvListeners }) } } const App = { compatConfig: { MODE: 3, RENDER_FUNCTION: 'suppress-warning' }, name: 'App', props: ['listenClick', 'listenFocus', 'listenBlur'], computed: { listeners() { const listeners = {} if (this.listenClick) { listeners.click = event => this.$emit('click', event) } if (this.listenFocus) { listeners.focus = event => this.$emit('focus', event) } if (this.listenBlur) { listeners.blur = event => this.$emit('blur', event) } return listeners } }, render(h) { return h(BTest, { on: this.listeners }) } } const wrapper = mount(App) expect(wrapper).toBeDefined() expect(wrapper.vm).toBeDefined() expect(wrapper.element.tagName).toBe('BUTTON') const $test = wrapper.findComponent(BTest) expect($test.exists()).toBe(true) expect($test.vm).toBeDefined() expect($test.vm.bvListeners).toBeDefined() expect($test.vm.bvListeners.click).toBeUndefined() expect($test.vm.bvListeners.focus).toBeUndefined() expect($test.vm.bvListeners.blur).toBeUndefined() // Correctly adds new listeners await wrapper.setProps({ listenClick: true, listenFocus: true }) expect($test.vm.bvListeners.click).toBeDefined() expect($test.vm.bvListeners.focus).toBeDefined() expect($test.vm.bvListeners.blur).toBeUndefined() // Correctly updates listeners await wrapper.setProps({ listenClick: false, listenBlur: true }) expect($test.vm.bvListeners.click).toBeUndefined() expect($test.vm.bvListeners.focus).toBeDefined() expect($test.vm.bvListeners.blur).toBeDefined() // Correctly removes listeners await wrapper.setProps({ listenClick: false, listenFocus: false, listenBlur: false }) expect($test.vm.bvListeners.click).toBeUndefined() expect($test.vm.bvListeners.focus).toBeUndefined() expect($test.vm.bvListeners.blur).toBeUndefined() wrapper.destroy() }) it('does not re-render parent child components', async () => { let input1RenderCount = 0 let input2RenderCount = 0 const Input1 = { compatConfig: { MODE: 3, RENDER_FUNCTION: 'suppress-warning', INSTANCE_LISTENERS: 'suppress-warning' }, props: ['value'], render(h) { input1RenderCount++ return h('input', { attrs: { value: this.value }, domProps: { value: this.value }, on: { ...this.$listeners, input: e => this.$emit('input', e.target.value) } }) } } const Input2 = { compatConfig: { MODE: 3, RENDER_FUNCTION: 'suppress-warning', INSTANCE_LISTENERS: 'suppress-warning' }, props: ['value'], mixins: [listenersMixin], render(h) { input2RenderCount++ return h('input', { attrs: { value: this.value }, domProps: { value: this.value }, on: { ...this.bvListeners, input: e => this.$emit('input', e.target.value) } }) } } const App1 = { components: { Input1 }, props: ['listenFocus1', 'listenFocus2'], methods: { emit1($event) { if (this.listenFocus1) { this.$emit('focus1', $event) } }, emit2($event) { if (this.listenFocus2) { this.$emit('focus2', $event) } } }, template: `<div> <Input1 @focus="emit1" /> <Input1 @focus="emit2" /> </div>` } const App2 = { components: { Input2 }, props: ['listenFocus1', 'listenFocus2'], methods: { emit1($event) { if (this.listenFocus1) { this.$emit('focus1', $event) } }, emit2($event) { if (this.listenFocus2) { this.$emit('focus2', $event) } } }, template: `<div> <Input2 @focus="emit1" /> <Input2 @focus="emit2" /> </div>` } const wrapper1 = mount(App1, { attachTo: document.body }) const wrapper2 = mount(App2, { attachTo: document.body }) // --- `Input1` tests --- const $inputs1 = wrapper1.findAllComponents(Input1) expect($inputs1.length).toBe(2) expect($inputs1.at(0)).toBeDefined() expect($inputs1.at(1)).toBeDefined() expect(wrapper1.emitted().focus1).not.toBeTruthy() expect(wrapper1.emitted().focus2).not.toBeTruthy() expect(input1RenderCount).toBe(2) await $inputs1.at(0).trigger('focus') expect(wrapper1.emitted().focus1).not.toBeTruthy() await $inputs1.at(1).trigger('focus') expect(wrapper1.emitted().focus2).not.toBeTruthy() expect(input1RenderCount).toBe(2) // Enable focus events for the first input and trigger it await wrapper1.setProps({ listenFocus1: true }) await $inputs1.at(0).trigger('focus') expect(wrapper1.emitted().focus1).toBeTruthy() expect(wrapper1.emitted().focus2).not.toBeTruthy() // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) expect(input1RenderCount).toBe(isVue3 ? 2 : 4) // Enable focus events for the second input and trigger it await wrapper1.setProps({ listenFocus2: true }) await $inputs1.at(1).trigger('focus') expect(wrapper1.emitted().focus1).toBeTruthy() expect(wrapper1.emitted().focus2).toBeTruthy() // Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257) expect(input1RenderCount).toBe(isVue3 ? 2 : 6) // --- `Input2` tests --- const $inputs2 = wrapper2.findAllComponents(Input2) expect($inputs2.length).toBe(2) expect($inputs2.at(0)).toBeDefined() expect($inputs2.at(1)).toBeDefined() expect(wrapper2.emitted().focus1).not.toBeTruthy() expect(wrapper2.emitted().focus2).not.toBeTruthy() expect(input2RenderCount).toBe(2) await $inputs2.at(0).trigger('focus') expect(wrapper2.emitted().focus1).not.toBeTruthy() await $inputs2.at(1).trigger('focus') expect(wrapper2.emitted().focus2).not.toBeTruthy() expect(input2RenderCount).toBe(2) // Enable focus events for the first input and trigger it await wrapper2.setProps({ listenFocus1: true }) await $inputs2.at(0).trigger('focus') expect(wrapper2.emitted().focus1).toBeTruthy() expect(wrapper2.emitted().focus2).not.toBeTruthy() // With `listenersMixin` only the affected `Input2` is re-rendered expect(input2RenderCount).toBe(2) // Enable focus events for the second input and trigger it await wrapper2.setProps({ listenFocus2: true }) await $inputs2.at(1).trigger('focus') expect(wrapper2.emitted().focus1).toBeTruthy() expect(wrapper2.emitted().focus2).toBeTruthy() // With `listenersMixin` only the affected `Input2` is re-rendered expect(input2RenderCount).toBe(2) wrapper1.destroy() wrapper2.destroy() }) })