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
195 lines (164 loc) • 5.79 kB
JavaScript
import { isVue3 } from '../vue'
import { mount } from '@vue/test-utils'
import { attrsMixin } from './attrs'
// Note: The following tests indirectly test `utils/cache`
describe('mixins > attrs', () => {
it('works', async () => {
const BTest = {
name: 'BTest',
mixins: [attrsMixin],
inheritAttrs: false,
render(h) {
return h('section', [h('article', { attrs: this.bvAttrs })])
}
}
const App = {
name: 'App',
props: {
attrs: {
type: Object,
default: () => ({})
}
},
render(h) {
return h(BTest, { attrs: this.attrs })
}
}
const wrapper = mount(App)
expect(wrapper).toBeDefined()
expect(wrapper.vm).toBeDefined()
expect(wrapper.element.tagName).toBe('SECTION')
const $test = wrapper.findComponent(BTest)
expect($test.exists()).toBe(true)
expect($test.vm).toBeDefined()
const $section = $test.find('section')
expect($section.exists()).toBe(true)
const $article = $test.find('article')
expect($article.exists()).toBe(true)
expect($section.attributes()).toEqual({})
expect($article.attributes()).toEqual({})
expect($test.vm.bvAttrs).toBeDefined()
expect($test.vm.bvAttrs.foo).toBeUndefined()
expect($test.vm.bvAttrs.baz).toBeUndefined()
// Correctly adds new attrs data
await wrapper.setProps({
attrs: { foo: 'bar' }
})
expect($section.attributes()).toEqual({})
expect($article.attributes()).toEqual({ foo: 'bar' })
expect($test.vm.bvAttrs.foo).toEqual('bar')
expect($test.vm.bvAttrs.baz).toBeUndefined()
// Correctly updates attrs data
await wrapper.setProps({
attrs: { foo: 'bar', baz: 'biz' }
})
expect($section.attributes()).toEqual({})
expect($article.attributes()).toEqual({ foo: 'bar', baz: 'biz' })
expect($test.vm.bvAttrs.foo).toEqual('bar')
expect($test.vm.bvAttrs.baz).toEqual('biz')
// Correctly removes attrs data
await wrapper.setProps({
attrs: { foo: 'bar' }
})
expect($section.attributes()).toEqual({})
expect($article.attributes()).toEqual({ foo: 'bar' })
expect($test.vm.bvAttrs.foo).toEqual('bar')
expect($test.vm.bvAttrs.baz).toBeUndefined()
// Correctly removes all attrs data
await wrapper.setProps({ attrs: {} })
expect($section.attributes()).toEqual({})
expect($article.attributes()).toEqual({})
expect($test.vm.bvAttrs.foo).toBeUndefined()
expect($test.vm.bvAttrs.baz).toBeUndefined()
wrapper.destroy()
})
it('does not re-render parent child components', async () => {
let input1RenderCount = 0
let input2RenderCount = 0
const Input1 = {
props: ['value'],
render(h) {
input1RenderCount++
return h('input', {
attrs: { ...this.$attrs, value: this.value },
domProps: { value: this.value },
on: { input: e => this.$emit('input', e.target.value) }
})
}
}
const Input2 = {
props: ['value'],
mixins: [attrsMixin],
render(h) {
input2RenderCount++
return h('input', {
attrs: { ...this.bvAttrs, value: this.value },
domProps: { value: this.value },
on: { input: e => this.$emit('input', e.target.value) }
})
}
}
const App1 = {
components: { Input1 },
props: ['value1', 'value2'],
template: `<div>
<Input1 v-model="value1" />
<Input1 v-model="value2" />
</div>`
}
const App2 = {
components: { Input2 },
props: ['value1', 'value2'],
template: `<div>
<Input2 v-model="value1" />
<Input2 v-model="value2" />
</div>`
}
const wrapper1 = mount(App1)
const wrapper2 = mount(App2)
const $inputs1 = wrapper1.findAllComponents(Input1)
expect($inputs1.length).toBe(2)
expect($inputs1.at(0)).toBeDefined()
expect($inputs1.at(0).vm.value).toBe(undefined)
expect($inputs1.at(1)).toBeDefined()
expect($inputs1.at(1).vm.value).toBe(undefined)
expect(input1RenderCount).toBe(2)
const $inputs2 = wrapper2.findAllComponents(Input2)
expect($inputs2.length).toBe(2)
expect($inputs2.at(0)).toBeDefined()
expect($inputs2.at(0).vm.value).toBe(undefined)
expect($inputs2.at(1)).toBeDefined()
expect($inputs2.at(1).vm.value).toBe(undefined)
expect(input2RenderCount).toBe(2)
// Update the value for the first `Input1`
await wrapper1.setProps({ value1: 'foo' })
expect($inputs1.at(0).vm.value).toBe('foo')
expect($inputs1.at(1).vm.value).toBe(undefined)
if (!isVue3) {
// Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257)
expect(input1RenderCount).toBe(4)
}
// Update the value for the second `Input1`
await wrapper1.setProps({ value2: 'bar' })
expect($inputs1.at(0).vm.value).toBe('foo')
expect($inputs1.at(1).vm.value).toBe('bar')
if (!isVue3) {
// Both `Input1`'s are re-rendered (See: https://github.com/vuejs/vue/issues/7257)
expect(input1RenderCount).toBe(6)
}
// Update the value for the first `Input2`
await wrapper2.setProps({ value1: 'foo' })
expect($inputs2.at(0).vm.value).toBe('foo')
expect($inputs2.at(1).vm.value).toBe(undefined)
// With `attrsMixin` only the affected `Input2` is re-rendered
expect(input2RenderCount).toBe(3)
// Update the value for the second `Input2`
await wrapper2.setProps({ value2: 'bar' })
expect($inputs2.at(0).vm.value).toBe('foo')
expect($inputs2.at(1).vm.value).toBe('bar')
// With `attrsMixin` only the affected `Input2` is re-rendered
expect(input2RenderCount).toBe(4)
wrapper1.destroy()
wrapper2.destroy()
})
})