test(10-05): bring every SPA module, composable and component under Vitest
- 41 unit and component suites under admin/tests/{app,state,shell,list,form,relation,views,ui}
covering states and a11y roles; every src module is imported by a test
- typed fixture helper assigns each JSON fixture to its generated OpenAPI type
- fix: iconFor ignores inherited object members such as "constructor"
- fix: field controls import ./control instead of the registry (import cycle
left a renderer unregistered depending on module load order)
- fix: dropdown shows the placeholder for an unknown stored value next to an emptyOption
- fix: list announces a failed schema load even when the rows arrive after it
- tailwind no longer scans admin/tests; boardwalk/dist rebuilt
This commit is contained in:
61
admin/tests/form/FormTabs.test.ts
Normal file
61
admin/tests/form/FormTabs.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import { enableAutoUnmount, mount } from '@vue/test-utils'
|
||||
import FormTabs from '../../src/components/form/FormTabs.vue'
|
||||
import type { TabItem } from '../../src/components/form/formState'
|
||||
import { keydown, resetState } from '../helpers'
|
||||
|
||||
const tabs: TabItem[] = [
|
||||
{ key: 'default', label: 'Podstawowe', errors: 0 },
|
||||
{ key: 'tab:Details', label: 'Details', errors: 2 },
|
||||
{ key: 'tab:Members', label: 'Members', errors: 1 },
|
||||
]
|
||||
|
||||
function mountTabs(modelValue = 'default') {
|
||||
return mount(FormTabs, { props: { tabs, modelValue, idPrefix: 'f' }, attachTo: document.body })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
resetState()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
enableAutoUnmount(afterEach)
|
||||
|
||||
describe('form tabs', () => {
|
||||
it('is a tablist of tabs with roving tabindex, aria-selected and aria-controls', () => {
|
||||
const wrapper = mountTabs('tab:Details')
|
||||
expect(wrapper.find('[role="tablist"]').exists()).toBe(true)
|
||||
const items = wrapper.findAll('[role="tab"]')
|
||||
expect(items.map((tab) => tab.attributes('aria-selected'))).toEqual(['false', 'true', 'false'])
|
||||
expect(items.map((tab) => tab.attributes('tabindex'))).toEqual(['-1', '0', '-1'])
|
||||
expect(items.map((tab) => tab.attributes('id'))).toEqual(['f-tab-0', 'f-tab-1', 'f-tab-2'])
|
||||
expect(items.map((tab) => tab.attributes('aria-controls'))).toEqual(['f-panel-0', 'f-panel-1', 'f-panel-2'])
|
||||
})
|
||||
|
||||
it('badges tabs with invalid fields with a plural label', () => {
|
||||
const wrapper = mountTabs()
|
||||
const badges = wrapper.findAll('[data-tab-errors]')
|
||||
expect(badges.map((badge) => [badge.text(), badge.attributes('aria-label')])).toEqual([
|
||||
['2', '2 błędy'],
|
||||
['1', '1 błąd'],
|
||||
])
|
||||
})
|
||||
|
||||
it('selects on click and moves with the arrow keys, wrapping and moving focus', async () => {
|
||||
const wrapper = mountTabs()
|
||||
await wrapper.findAll('[role="tab"]')[2]!.trigger('click')
|
||||
expect(wrapper.emitted('update:modelValue')!.at(-1)).toEqual(['tab:Members'])
|
||||
|
||||
const first = wrapper.findAll('[role="tab"]')[0]!.element
|
||||
expect(keydown(first, 'ArrowLeft').defaultPrevented).toBe(true)
|
||||
expect(wrapper.emitted('update:modelValue')!.at(-1)).toEqual(['tab:Members'])
|
||||
expect(document.activeElement?.id).toBe('f-tab-2')
|
||||
keydown(first, 'ArrowRight')
|
||||
expect(wrapper.emitted('update:modelValue')!.at(-1)).toEqual(['tab:Details'])
|
||||
expect(document.activeElement?.id).toBe('f-tab-1')
|
||||
expect(keydown(first, 'Enter').defaultPrevented).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user