import { describe, expect, it } from 'vitest' import { userEvent } from 'vitest/browser' import { defineComponent, h } from 'vue' import { page, render } from '~/test' import SmallTabs from './SmallTabs.vue' import SmallTabsPane from './SmallTabsPane.vue' function createSmallTabs(children: number) { return defineComponent({ setup: () => () => h(SmallTabs, null, { default: () => Array.from({ length: children }, (_, i) => h(SmallTabsPane, { title: `title-${i}` }, () => `content-${i}`), ), }), }) } describe('SmallTabs', () => { it('has accessible elements', async () => { const result = await render(createSmallTabs(2)) // a tablist with two elements inside const tablist = page.getByRole('tablist') const tabs = tablist.getByRole('tab') const firstTab = tabs.first() const secondTab = tabs.last() await expect.element(tablist).toBeInTheDocument() await expect.element(result.locator).toMatchAriaInlineSnapshot(` - tablist: - tab "title-0" [selected] - tab "title-1" - tabpanel "title-0": content-0 `) expect(tabs.all()).toHaveLength(2) await expect.element(firstTab).toHaveAttribute('aria-selected', 'true') await expect.element(secondTab).toHaveAttribute('aria-selected', 'false') // two tab panels, with one hidden const panels = page.getByRole('tabpanel', { includeHidden: true }) const firstPanel = panels.first() const secondPanel = panels.last() expect(panels.all()).toHaveLength(2) await expect.element(firstPanel).not.toHaveAttribute('hidden') await expect.element(secondPanel).toHaveAttribute('hidden') // panels should be labelled by their tab button await expect .element(firstPanel) .toHaveAttribute('aria-labelledby', firstTab.element().getAttribute('id')) await expect .element(secondPanel) .toHaveAttribute('aria-labelledby', secondTab.element().getAttribute('id')) await expect .element(firstTab) .toHaveAttribute('aria-controls', firstPanel.element().getAttribute('id')) await expect .element(secondTab) .toHaveAttribute('aria-controls', secondPanel.element().getAttribute('id')) }) it('opens one panel at a time', async () => { const tabsLimit = 5 const result = await render(createSmallTabs(tabsLimit)) const tabs = page.getByRole('tablist').getByRole('tab') const panels = page.getByRole('tabpanel', { includeHidden: true }) for (let tabIndex = 0; tabIndex < tabsLimit; tabIndex += 1) { const activeTab = tabs.nth(tabIndex) const activePanel = panels.nth(tabIndex) await userEvent.click(activeTab) await expect .element(tabs.and(page.getByRole('tab', { selected: true }))) .toBe(activeTab.element()) await expect.element(page.getByRole('tabpanel')).toBe(activePanel.element()) } expect(result.container).toMatchAriaInlineSnapshot(` - tablist: - tab "title-0" - tab "title-1" - tab "title-2" - tab "title-3" - tab "title-4" [selected] - tabpanel "title-4": content-4 `) }) })