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
837 lines (691 loc) • 26.7 kB
JavaScript
import { mount } from '@vue/test-utils'
import { waitNT } from '../../../tests/utils'
import { BLink } from '../link/link'
import { BTab } from './tab'
import { BTabs } from './tabs'
describe('tabs', () => {
it('default has expected classes and structure', async () => {
const wrapper = mount(BTabs)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
expect(wrapper.element.tagName).toBe('DIV')
expect(wrapper.classes()).toContain('tabs')
expect(wrapper.classes()).not.toContain('row')
expect(wrapper.classes()).not.toContain('no-gutters')
expect(wrapper.attributes('id')).toBeDefined()
wrapper.destroy()
})
it('default has expected data state', async () => {
const wrapper = mount(BTabs)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
expect(wrapper.vm.currentTab).toBe(-1)
expect(wrapper.vm.tabs.length).toBe(0)
wrapper.destroy()
})
it('has correct card classes when prop card is true', async () => {
const wrapper = mount(BTabs, {
propsData: { card: true },
slots: {
default: {
components: { BTab },
template: '<div><b-tab /><b-tab /><b-tab /></div>'
}
}
})
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
expect(wrapper.element.tagName).toBe('DIV')
expect(wrapper.classes()).toContain('tabs')
expect(wrapper.findAll('.card-header').length).toBe(1)
expect(wrapper.findAll('ul').length).toBe(1)
expect(wrapper.find('ul').classes()).toContain('nav')
expect(wrapper.find('ul').classes()).toContain('nav-tabs')
expect(wrapper.find('ul').classes()).toContain('card-header-tabs')
wrapper.destroy()
})
it('has correct card classes when props card and vertical are true', async () => {
const wrapper = mount(BTabs, {
propsData: { card: true, vertical: true },
slots: {
default: {
components: { BTab },
template: '<div><b-tab /><b-tab /><b-tab /></div>'
}
}
})
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
expect(wrapper.element.tagName).toBe('DIV')
expect(wrapper.classes()).toContain('tabs')
expect(wrapper.classes()).toContain('row')
expect(wrapper.classes()).toContain('no-gutters')
expect(wrapper.findAll('.card-header').length).toBe(1)
expect(wrapper.findAll('ul').length).toBe(1)
expect(wrapper.find('ul').classes()).toContain('nav')
expect(wrapper.find('ul').classes()).toContain('nav-tabs')
expect(wrapper.find('ul').classes()).toContain('card-header')
expect(wrapper.find('ul').classes()).toContain('flex-column')
expect(wrapper.find('ul').classes()).toContain('h-100')
expect(wrapper.find('ul').classes()).toContain('border-bottom-0')
expect(wrapper.find('ul').classes()).toContain('rounded-0')
expect(wrapper.findAll('.tab-content.col').length).toBe(1)
expect(wrapper.findAll('.col-auto').length).toBe(1)
wrapper.destroy()
})
it('sets correct tab active for initial value', async () => {
const tabIndex = 1
const wrapper = mount(BTabs, {
propsData: { value: tabIndex },
slots: {
default: {
components: { BTab },
template: '<div><b-tab /><b-tab /><b-tab /></div>'
}
}
})
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
expect(wrapper.vm.currentTab).toBe(tabIndex)
expect(wrapper.vm.tabs.length).toBe(3)
expect(wrapper.vm.tabs[tabIndex].localActive).toBe(true)
wrapper.destroy()
})
it('sets correct tab active when first tab is disabled', async () => {
const App = {
render(h) {
return h(BTabs, [
h(BTab, { props: { disabled: true } }, 'tab 0'),
h(BTab, { props: {} }, 'tab 1'),
h(BTab, { props: {} }, 'tab 2')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 2nd tab (index 1) to be active
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.vm.tabs[1].localActive).toBe(true)
expect($tabs.emitted('input')).toBeDefined()
expect($tabs.emitted('input').length).toBe(1)
// Should emit index of 1 (2nd tab)
expect($tabs.emitted('input')[0][0]).toBe(1)
wrapper.destroy()
})
it('sets current index based on active prop of b-tab', async () => {
const App = {
render(h) {
return h(BTabs, [
h(BTab, { props: { active: false } }, 'tab 0'),
h(BTab, { props: { active: true } }, 'tab 1'),
h(BTab, { props: { active: false } }, 'tab 2')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 2nd tab (index 1) to be active
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.vm.tabs[1].localActive).toBe(true)
expect($tabs.emitted('input')).toBeDefined()
expect($tabs.emitted('input').length).toBe(1)
// Should emit index of 1 (2nd tab)
expect($tabs.emitted('input')[0][0]).toBe(1)
wrapper.destroy()
})
it('selects first non-disabled tab when active tab disabled', async () => {
const App = {
props: {
activeTab: { type: Number, default: 1 }
},
render(h) {
const { activeTab } = this
return h(BTabs, [
h(BTab, { props: { active: activeTab === 0, disabled: true } }, 'Tab 1'),
h(BTab, { props: { active: activeTab === 1 } }, 'Tab 2'),
h(BTab, { props: { active: activeTab === 2 } }, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 2nd tab (index 1) to be active
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.findAllComponents(BTab).at(0).vm.localActive).toBe(false)
expect($tabs.findAllComponents(BTab).at(1).vm.localActive).toBe(true)
expect($tabs.findAllComponents(BTab).at(2).vm.localActive).toBe(false)
expect($tabs.emitted('input')).toBeDefined()
expect($tabs.emitted('input').length).toBe(1)
// Should emit index of 1 (2nd tab)
expect($tabs.emitted('input')[0][0]).toBe(1)
// Deactivate current tab (BTab 2, index 1)
await wrapper.setProps({ activeTab: -1 })
// Expect last tab (index 2) to be active
expect($tabs.vm.currentTab).toBe(2)
expect($tabs.findAllComponents(BTab).at(0).vm.localActive).toBe(false)
expect($tabs.findAllComponents(BTab).at(1).vm.localActive).toBe(false)
expect($tabs.findAllComponents(BTab).at(2).vm.localActive).toBe(true)
expect($tabs.emitted('input').length).toBe(2)
expect($tabs.emitted('input')[1][0]).toBe(2)
wrapper.destroy()
})
it('v-model works', async () => {
const App = {
props: {
activeTab: { type: Number, default: 0 }
},
render(h) {
return h(BTabs, { props: { value: this.activeTab } }, [
h(BTab, 'Tab 1'),
h(BTab, 'Tab 2'),
h(BTab, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.vm.tabs[0].localActive).toBe(true)
// It should not emit an input event as the value is the same
expect($tabs.emitted('input')).toBeUndefined()
// Set 2nd BTab to be active
await wrapper.setProps({ activeTab: 1 })
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.emitted('input').length).toBe(1)
// Should emit index of 1 (2nd tab)
expect($tabs.emitted('input')[0][0]).toBe(1)
// Set 3rd BTab to be active
await wrapper.setProps({ activeTab: 2 })
expect($tabs.vm.currentTab).toBe(2)
expect($tabs.emitted('input').length).toBe(2)
// Should emit index of 2 (3rd tab)
expect($tabs.emitted('input')[1][0]).toBe(2)
wrapper.destroy()
})
it('v-model works when trying to activate a disabled tab', async () => {
const App = {
props: {
activeTab: { type: Number, default: 0 }
},
render(h) {
return h(BTabs, { props: { value: this.activeTab } }, [
h(BTab, 'Tab 1'),
h(BTab, { props: { disabled: true } }, 'Tab 2'),
h(BTab, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.vm.tabs[0].localActive).toBe(true)
expect($tabs.emitted('input')).toBeUndefined()
// Try to set 2nd (disabled) BTab to be active
await wrapper.setProps({ activeTab: 1 })
// Will try activate next non-disabled tab instead (3rd tab, index 2)
expect($tabs.vm.currentTab).toBe(2)
expect($tabs.emitted('input').length).toBe(1)
// Should emit index of 2 (3rd tab)
expect($tabs.emitted('input')[0][0]).toBe(2)
// Needed for test since value not bound to actual v-model on App
await wrapper.setProps({ activeTab: 2 })
// Try and set 2nd BTab to be active
await wrapper.setProps({ activeTab: 1 })
// Will find the previous non-disabled tab (1st tab, index 0)
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.emitted('input').length).toBe(2)
// Should emit index of 0 (1st tab)
expect($tabs.emitted('input')[1][0]).toBe(0)
wrapper.destroy()
})
it('`activate-tab` event works', async () => {
const App = {
props: {
activeTab: { type: Number, default: 0 }
},
methods: {
preventTab(next, prev, bvEvent) {
// Prevent 3rd tab (index === 2) from activating
if (next === 2) {
bvEvent.preventDefault()
}
}
},
render(h) {
return h(
BTabs,
{
props: { value: this.activeTab },
on: { 'activate-tab': this.preventTab }
},
[h(BTab, 'Tab 1'), h(BTab, 'Tab 2'), h(BTab, 'Tab 3')]
)
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.vm.tabs[0].localActive).toBe(true)
expect($tabs.emitted('input')).toBeUndefined()
expect($tabs.emitted('activate-tab')).toBeUndefined()
// Set 2nd BTab to be active
await wrapper.setProps({ activeTab: 1 })
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.emitted('input')).toBeDefined()
expect($tabs.emitted('input').length).toBe(1)
expect($tabs.emitted('input')[0][0]).toBe(1)
expect($tabs.emitted('activate-tab')).toBeDefined()
expect($tabs.emitted('activate-tab').length).toBe(1)
expect($tabs.emitted('activate-tab')[0][0]).toBe(1)
expect($tabs.emitted('activate-tab')[0][1]).toBe(0)
expect($tabs.emitted('activate-tab')[0][2]).toBeDefined()
expect($tabs.emitted('activate-tab')[0][2].vueTarget).toBe($tabs.vm)
// Attempt to set 3rd BTab to be active
await wrapper.setProps({ activeTab: 2 })
expect($tabs.vm.currentTab).toBe(1)
expect($tabs.emitted('input')).toBeDefined()
expect($tabs.emitted('input').length).toBe(2)
expect($tabs.emitted('input')[1][0]).toBe(1)
expect($tabs.emitted('activate-tab').length).toBe(2)
expect($tabs.emitted('activate-tab')[1][0]).toBe(2)
expect($tabs.emitted('activate-tab')[1][1]).toBe(1)
expect($tabs.emitted('activate-tab')[1][2]).toBeDefined()
expect($tabs.emitted('activate-tab')[1][2].vueTarget).toBe($tabs.vm)
expect($tabs.emitted('activate-tab')[1][2].defaultPrevented).toBe(true)
wrapper.destroy()
})
it('clicking on tab activates the tab, and tab emits click event', async () => {
const App = {
render(h) {
return h(BTabs, { props: { value: 0 } }, [
h(BTab, { props: { title: 'one' } }, 'tab 0'),
h(BTab, { props: { title: 'two' } }, 'tab 1'),
h(BTab, { props: { title: 'three' } }, 'tab 2')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
const tab1 = $tabs.findAllComponents(BTab).at(0)
const tab2 = $tabs.findAllComponents(BTab).at(1)
const tab3 = $tabs.findAllComponents(BTab).at(2)
expect(wrapper.findAll('.nav-link')).toBeDefined()
expect(wrapper.findAll('.nav-link').length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
// Try to set 2nd BTab to be active via click
expect(tab2.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(1)
.trigger('click')
expect($tabs.vm.currentTab).toBe(1)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(true)
expect(tab3.vm.localActive).toBe(false)
expect(tab2.emitted('click')).toBeDefined()
// Try to set 3rd BTab to be active via click
expect(tab3.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(2)
.trigger('click')
expect($tabs.vm.currentTab).toBe(2)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(true)
expect(tab3.emitted('click')).toBeDefined()
// Try to set 1st BTab to be active via click (space === click in keynav mode)
expect(tab1.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(0)
.trigger('keydown.space')
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
expect(tab1.emitted('click')).toBeDefined()
wrapper.destroy()
})
it('pressing space on tab activates the tab, and tab emits click event', async () => {
const App = {
render(h) {
return h(BTabs, { props: { value: 0, noKeyNav: true } }, [
h(BTab, { props: { title: 'one' } }, 'tab 0'),
h(BTab, { props: { title: 'two' } }, 'tab 1'),
h(BTab, { props: { title: 'three' } }, 'tab 2')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
const tab1 = $tabs.findAllComponents(BTab).at(0)
const tab2 = $tabs.findAllComponents(BTab).at(1)
const tab3 = $tabs.findAllComponents(BTab).at(2)
expect(wrapper.findAll('.nav-link')).toBeDefined()
expect(wrapper.findAll('.nav-link').length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
// Try to set 2nd BTab to be active via space keypress
expect(tab2.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(1)
.trigger('keydown.space')
expect($tabs.vm.currentTab).toBe(1)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(true)
expect(tab3.vm.localActive).toBe(false)
expect(tab2.emitted('click')).toBeDefined()
// Try to set 3rd BTab to be active via space keypress
expect(tab3.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(2)
.trigger('keydown.space')
expect($tabs.vm.currentTab).toBe(2)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(true)
expect(tab3.emitted('click')).toBeDefined()
// Try to set 1st BTab to be active via space keypress
expect(tab1.emitted('click')).toBeUndefined()
await wrapper
.findAll('.nav-link')
.at(0)
.trigger('keydown.space')
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
expect(tab1.emitted('click')).toBeDefined()
wrapper.destroy()
})
it('key nav works', async () => {
const App = {
render(h) {
return h(BTabs, { props: { value: 0 } }, [
h(BTab, { props: { title: 'one' } }, 'tab 0'),
h(BTab, { props: { title: 'two' } }, 'tab 1'),
h(BTab, { props: { title: 'three' } }, 'tab 2')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
const tab1 = $tabs.findAllComponents(BTab).at(0)
const tab2 = $tabs.findAllComponents(BTab).at(1)
const tab3 = $tabs.findAllComponents(BTab).at(2)
expect(wrapper.findAll('.nav-link')).toBeDefined()
expect(wrapper.findAll('.nav-link').length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
// RIGHT moves to next tab
await wrapper
.findAllComponents(BLink)
.at(0)
.trigger('keydown.right')
expect($tabs.vm.currentTab).toBe(1)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(true)
expect(tab3.vm.localActive).toBe(false)
// END key moves to last tab
await wrapper
.findAllComponents(BLink)
.at(1)
.trigger('keydown.end')
expect($tabs.vm.currentTab).toBe(2)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(true)
// LEFT moves to previous tab
await wrapper
.findAllComponents(BLink)
.at(2)
.trigger('keydown.left')
expect($tabs.vm.currentTab).toBe(1)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(true)
expect(tab3.vm.localActive).toBe(false)
// HOME moves to first tab
await wrapper
.findAllComponents(BLink)
.at(1)
.trigger('keydown.home')
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
wrapper.destroy()
})
it('disabling active tab selects first non-disabled tab', async () => {
const App = {
props: {
disabledTabs: { type: Array, default: () => [] }
},
render(h) {
const { disabledTabs } = this
return h(BTabs, { props: { value: 2 } }, [
h(BTab, { props: { disabled: disabledTabs.indexOf(0) !== -1 } }, 'Tab 1'),
h(BTab, { props: { disabled: disabledTabs.indexOf(1) !== -1 } }, 'Tab 2'),
h(BTab, { props: { disabled: disabledTabs.indexOf(2) !== -1 } }, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
const tab1 = $tabs.findAllComponents(BTab).at(0)
const tab2 = $tabs.findAllComponents(BTab).at(1)
const tab3 = $tabs.findAllComponents(BTab).at(2)
// Expect 3rd tab (index 2) to be active
expect($tabs.vm.currentTab).toBe(2)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(true)
// Disable 3rd tab
await wrapper.setProps({ disabledTabs: [2] })
// Expect 1st tab to be active
expect($tabs.vm.currentTab).toBe(0)
expect(tab1.vm.localActive).toBe(true)
expect(tab2.vm.localActive).toBe(false)
expect(tab3.vm.localActive).toBe(false)
// Enable 3rd tab and Disable 1st tab
await wrapper.setProps({ disabledTabs: [0] })
// Expect 2nd tab to be active
expect($tabs.vm.currentTab).toBe(1)
expect(tab1.vm.localActive).toBe(false)
expect(tab2.vm.localActive).toBe(true)
expect(tab3.vm.localActive).toBe(false)
wrapper.destroy()
})
it('tab title slots are reactive', async () => {
const App = {
render(h) {
return h(BTabs, { props: { value: 2 } }, [
h(BTab, { props: { title: 'original' } }, 'tab content')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(1)
// Expect tab button content to be `original`
expect(wrapper.find('.nav-link').text()).toBe('original')
// Get the BTab's instance
const tabVm = wrapper.findComponent(BTab).vm
expect(tabVm).toBeDefined()
// Change title slot content
tabVm.$slots.title = [tabVm.$createElement('span', 'foobar')]
tabVm.$forceUpdate()
await waitNT(wrapper.vm)
// Expect tab button content to be `foobar`
expect(wrapper.find('.nav-link').text()).toBe('foobar')
wrapper.destroy()
})
it('"active-nav-item-class" is applied to active nav item', async () => {
const activeNavItemClass = 'text-success'
const App = {
props: {
activeTab: { type: Number, default: 0 }
},
render(h) {
return h(BTabs, { props: { value: this.activeTab, activeNavItemClass } }, [
h(BTab, 'Tab 1'),
h(BTab, 'Tab 2'),
h(BTab, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
const getNavItemByTab = tab => wrapper.find(`#${tab.$el.id}___BV_tab_button__`)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.vm.tabs[0].localActive).toBe(true)
// Expect 1st tabs nav item to have "active-nav-item-class" applied
expect(getNavItemByTab($tabs.vm.tabs[0]).classes(activeNavItemClass)).toBe(true)
// Set 2nd tab to be active
wrapper.setProps({ activeTab: 1 })
await waitNT(wrapper.vm)
expect($tabs.vm.currentTab).toBe(1)
// Expect 2nd tabs nav item to have "active-nav-item-class" applied
expect(getNavItemByTab($tabs.vm.tabs[1]).classes(activeNavItemClass)).toBe(true)
// Expect 1st tabs nav item to don't have "active-nav-item-class" applied anymore
expect(getNavItemByTab($tabs.vm.tabs[0]).classes(activeNavItemClass)).toBe(false)
wrapper.destroy()
})
it('"active-tab-class" is applied to active tab', async () => {
const activeTabClass = 'text-success'
const App = {
props: {
activeTab: { type: Number, default: 0 }
},
render(h) {
return h(BTabs, { props: { value: this.activeTab, activeTabClass } }, [
h(BTab, 'Tab 1'),
h(BTab, 'Tab 2'),
h(BTab, 'Tab 3')
])
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
// Expect 1st tab (index 0) to be active
expect($tabs.vm.currentTab).toBe(0)
expect($tabs.vm.tabs[0].localActive).toBe(true)
// Expect 1st tab to have "active-tab-class" applied
expect($tabs.vm.tabs[0].$el.classList.contains(activeTabClass)).toBe(true)
// Set 2nd tab to be active
await wrapper.setProps({ activeTab: 1 })
expect($tabs.vm.currentTab).toBe(1)
// Expect 2nd tab to have "active-tab-class" applied
expect($tabs.vm.tabs[1].$el.classList.contains(activeTabClass)).toBe(true)
// Expect 1st tab to don't have "active-tab-class" applied anymore
expect($tabs.vm.tabs[0].$el.classList.contains(activeTabClass)).toBe(false)
wrapper.destroy()
})
it('emits "changed" event when tabs change', async () => {
const App = {
props: {
tabs: {
type: Array,
default: () => ['Tab 1', 'Tab 2', 'Tab 3']
}
},
render(h) {
return h(BTabs, this.tabs.map(tab => h(BTab, tab)))
}
}
const wrapper = mount(App)
await waitNT(wrapper.vm)
expect(wrapper).toBeDefined()
const $tabs = wrapper.findComponent(BTabs)
expect($tabs).toBeDefined()
expect($tabs.findAllComponents(BTab).length).toBe(3)
expect($tabs.emitted('changed')).toBeDefined()
expect($tabs.emitted('changed').length).toBe(1)
expect($tabs.emitted('changed')[0][0].length).toBe(3)
expect($tabs.emitted('changed')[0][1].length).toBe(0)
// Add a tab
await wrapper.setProps({ tabs: ['Tab 1', 'Tab 2', 'Tab 3', 'Tab 4'] })
await waitNT(wrapper.vm)
expect($tabs.findAllComponents(BTab).length).toBe(4)
expect($tabs.emitted('changed')).toBeDefined()
expect($tabs.emitted('changed').length).toBe(2)
expect($tabs.emitted('changed')[1][0].length).toBe(4)
expect($tabs.emitted('changed')[1][1].length).toBe(3)
// Remove a tabs
await wrapper.setProps({ tabs: ['Tab 1', 'Tab 2'] })
await waitNT(wrapper.vm)
expect($tabs.findAllComponents(BTab).length).toBe(2)
expect($tabs.emitted('changed')).toBeDefined()
expect($tabs.emitted('changed').length).toBe(3)
expect($tabs.emitted('changed')[2][0].length).toBe(2)
expect($tabs.emitted('changed')[2][1].length).toBe(4)
wrapper.destroy()
})
})