@datametria/vue-components
Version:
DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 51 components + 10 composables with theming support, WCAG 2.2 AA, dark mode, responsive system
233 lines (191 loc) • 9.41 kB
text/typescript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import DatametriaTabs from '../DatametriaTabs.vue'
describe('DatametriaTabs', () => {
const tabs = ['Tab 1', 'Tab 2', 'Tab 3']
it('renders correctly', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
expect(wrapper.find('.dm-tabs').exists()).toBe(true)
})
it('renders all tabs', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
expect(tabButtons).toHaveLength(3)
expect(tabButtons[0].text()).toBe('Tab 1')
expect(tabButtons[1].text()).toBe('Tab 2')
expect(tabButtons[2].text()).toBe('Tab 3')
})
it('applies variant classes', () => {
const variants = ['default', 'pills', 'underline'] as const
variants.forEach(variant => {
const wrapper = mount(DatametriaTabs, { props: { tabs, variant } })
expect(wrapper.find(`.dm-tabs--${variant}`).exists()).toBe(true)
})
})
it('applies orientation classes', () => {
const horizontal = mount(DatametriaTabs, { props: { tabs, orientation: 'horizontal' } })
expect(horizontal.find('.dm-tabs--horizontal').exists()).toBe(true)
const vertical = mount(DatametriaTabs, { props: { tabs, orientation: 'vertical' } })
expect(vertical.find('.dm-tabs--vertical').exists()).toBe(true)
})
it('sets first tab as active by default', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
expect(wrapper.findAll('.dm-tabs__tab')[0].classes()).toContain('dm-tabs__tab--active')
})
it('respects modelValue prop', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 1 } })
expect(wrapper.findAll('.dm-tabs__tab')[1].classes()).toContain('dm-tabs__tab--active')
})
it('changes active tab on click', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
await wrapper.findAll('.dm-tabs__tab')[1].trigger('click')
expect(wrapper.findAll('.dm-tabs__tab')[1].classes()).toContain('dm-tabs__tab--active')
})
it('emits update:modelValue on tab click', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
await wrapper.findAll('.dm-tabs__tab')[2].trigger('click')
expect(wrapper.emitted('update:modelValue')).toBeTruthy()
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([2])
})
it('emits change event on tab click', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
await wrapper.findAll('.dm-tabs__tab')[1].trigger('click')
expect(wrapper.emitted('change')).toBeTruthy()
expect(wrapper.emitted('change')?.[0]).toEqual([1])
})
it('renders tab panels', () => {
const wrapper = mount(DatametriaTabs, {
props: { tabs },
slots: {
'panel-0': '<div class="panel-0">Panel 1</div>',
'panel-1': '<div class="panel-1">Panel 2</div>',
'panel-2': '<div class="panel-2">Panel 3</div>'
}
})
expect(wrapper.find('.panel-0').exists()).toBe(true)
expect(wrapper.find('.panel-1').exists()).toBe(true)
expect(wrapper.find('.panel-2').exists()).toBe(true)
})
it('shows only active panel', () => {
const wrapper = mount(DatametriaTabs, {
props: { tabs, modelValue: 1 },
slots: {
'panel-0': '<div class="panel-0">Panel 1</div>',
'panel-1': '<div class="panel-1">Panel 2</div>',
'panel-2': '<div class="panel-2">Panel 3</div>'
}
})
const panels = wrapper.findAll('.dm-tabs__panel')
expect(panels[0].classes()).not.toContain('dm-tabs__panel--active')
expect(panels[1].classes()).toContain('dm-tabs__panel--active')
expect(panels[2].classes()).not.toContain('dm-tabs__panel--active')
})
it('handles keyboard navigation - ArrowRight', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[0].trigger('keydown', { key: 'ArrowRight' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([1])
})
it('handles keyboard navigation - ArrowLeft', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 1 } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[1].trigger('keydown', { key: 'ArrowLeft' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([0])
})
it('handles keyboard navigation - Home', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 2 } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[2].trigger('keydown', { key: 'Home' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([0])
})
it('handles keyboard navigation - End', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 0 } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[0].trigger('keydown', { key: 'End' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([2])
})
it('wraps around with ArrowRight at last tab', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 2 } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[2].trigger('keydown', { key: 'ArrowRight' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([0])
})
it('wraps around with ArrowLeft at first tab', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 0 } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[0].trigger('keydown', { key: 'ArrowLeft' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([2])
})
it('renders tabs with icons', () => {
const tabsWithIcons = [
{ label: 'Home', icon: '🏠' },
{ label: 'Settings', icon: '⚙️' }
]
const wrapper = mount(DatametriaTabs, { props: { tabs: tabsWithIcons } })
expect(wrapper.findAll('.dm-tabs__icon')).toHaveLength(2)
expect(wrapper.findAll('.dm-tabs__icon')[0].text()).toBe('🏠')
})
it('renders tabs with badges', () => {
const tabsWithBadges = [
{ label: 'Messages', badge: '5' },
{ label: 'Notifications', badge: 10 }
]
const wrapper = mount(DatametriaTabs, { props: { tabs: tabsWithBadges } })
expect(wrapper.findAll('.dm-tabs__badge')).toHaveLength(2)
expect(wrapper.findAll('.dm-tabs__badge')[0].text()).toBe('5')
expect(wrapper.findAll('.dm-tabs__badge')[1].text()).toBe('10')
})
it('handles disabled tabs', async () => {
const tabsWithDisabled = [
{ label: 'Tab 1' },
{ label: 'Tab 2', disabled: true },
{ label: 'Tab 3' }
]
const wrapper = mount(DatametriaTabs, { props: { tabs: tabsWithDisabled } })
const disabledTab = wrapper.findAll('.dm-tabs__tab')[1]
expect(disabledTab.classes()).toContain('dm-tabs__tab--disabled')
expect(disabledTab.attributes('disabled')).toBeDefined()
await disabledTab.trigger('click')
expect(wrapper.emitted('update:modelValue')).toBeFalsy()
})
it('shows indicator by default', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs } })
expect(wrapper.find('.dm-tabs__indicator').exists()).toBe(true)
})
it('hides indicator when showIndicator is false', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, showIndicator: false } })
expect(wrapper.find('.dm-tabs__indicator').exists()).toBe(false)
})
it('has correct aria attributes', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, ariaLabel: 'Main tabs' } })
const header = wrapper.find('.dm-tabs__header')
expect(header.attributes('role')).toBe('tablist')
expect(header.attributes('aria-label')).toBe('Main tabs')
expect(header.attributes('aria-orientation')).toBe('horizontal')
})
it('updates aria-orientation for vertical tabs', () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, orientation: 'vertical' } })
const header = wrapper.find('.dm-tabs__header')
expect(header.attributes('aria-orientation')).toBe('vertical')
})
it('handles vertical keyboard navigation', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, orientation: 'vertical' } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[0].trigger('keydown', { key: 'ArrowDown' })
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([1])
await tabButtons[1].trigger('keydown', { key: 'ArrowUp' })
expect(wrapper.emitted('update:modelValue')?.[1]).toEqual([0])
})
it('ignores horizontal keys in vertical mode', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, orientation: 'vertical' } })
const tabButtons = wrapper.findAll('.dm-tabs__tab')
await tabButtons[0].trigger('keydown', { key: 'ArrowRight' })
expect(wrapper.emitted('update:modelValue')).toBeFalsy()
})
it('updates when modelValue prop changes', async () => {
const wrapper = mount(DatametriaTabs, { props: { tabs, modelValue: 0 } })
expect(wrapper.findAll('.dm-tabs__tab')[0].classes()).toContain('dm-tabs__tab--active')
await wrapper.setProps({ modelValue: 2 })
expect(wrapper.findAll('.dm-tabs__tab')[2].classes()).toContain('dm-tabs__tab--active')
})
})