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:
92
admin/tests/form/formState.test.ts
Normal file
92
admin/tests/form/formState.test.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import {
|
||||
contextAllows,
|
||||
DEFAULT_TAB,
|
||||
editablePayload,
|
||||
fieldErrors,
|
||||
focusField,
|
||||
initialValues,
|
||||
panelDomId,
|
||||
snapshot,
|
||||
tabDomId,
|
||||
tabOf,
|
||||
} from '../../src/components/form/formState'
|
||||
import { formField, formSchemaFixture } from '../fixtures/typed'
|
||||
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
describe('form state helpers', () => {
|
||||
it('keys tabs by label with a default tab for untabbed fields', () => {
|
||||
expect(tabOf(formField('name'))).toBe(DEFAULT_TAB)
|
||||
expect(tabOf(formField('serial'))).toBe('tab:Details')
|
||||
expect(tabDomId('field', 2)).toBe('field-tab-2')
|
||||
expect(panelDomId('field', 2)).toBe('field-panel-2')
|
||||
})
|
||||
|
||||
it('applies Winter context semantics', () => {
|
||||
expect(contextAllows(formField('name'), 'create')).toBe(true)
|
||||
expect(contextAllows(formField('serial'), 'update')).toBe(true)
|
||||
expect(contextAllows(formField('serial'), 'create')).toBe(false)
|
||||
expect(contextAllows(formField('batch'), 'create')).toBe(true)
|
||||
expect(contextAllows(formField('batch'), 'update')).toBe(false)
|
||||
expect(contextAllows({ ...formField('name'), context: [] }, 'update')).toBe(true)
|
||||
expect(contextAllows({ ...formField('name'), context: null as unknown as undefined }, 'update')).toBe(true)
|
||||
})
|
||||
|
||||
it('sends only editable, registered fields that hold a value', () => {
|
||||
const fields = formSchemaFixture.data.fields
|
||||
const body = editablePayload(fields, {
|
||||
name: 'Blue',
|
||||
code: undefined,
|
||||
color: '#fff',
|
||||
owner: 5,
|
||||
members: [1],
|
||||
tags: [3],
|
||||
active: false,
|
||||
unknown_key: 'x',
|
||||
})
|
||||
expect(body).toEqual({ name: 'Blue', tags: [3], active: false })
|
||||
})
|
||||
|
||||
it('starts a new record from defaults, toggles off and empty multiple relations', () => {
|
||||
const fields = [
|
||||
{ ...formField('name'), default: 'Unnamed' },
|
||||
formField('active'),
|
||||
formField('featured'),
|
||||
formField('tags'),
|
||||
formField('maker'),
|
||||
{ ...formField('weight'), default: 0 },
|
||||
]
|
||||
expect(initialValues(fields)).toEqual({ name: 'Unnamed', active: false, featured: false, tags: [], weight: 0 })
|
||||
})
|
||||
|
||||
it('normalizes 422 details into string lists and drops empty entries', () => {
|
||||
expect(
|
||||
fieldErrors({
|
||||
name: ['Required', '', 3],
|
||||
code: 'Taken',
|
||||
empty: [],
|
||||
blank: '',
|
||||
nested: { a: 1 },
|
||||
}),
|
||||
).toEqual({ name: ['Required'], code: ['Taken'] })
|
||||
expect(fieldErrors(undefined)).toEqual({})
|
||||
})
|
||||
|
||||
it('snapshots records independently of key order', () => {
|
||||
expect(snapshot({ a: 1, b: [2] })).toBe(snapshot({ b: [2], a: 1 }))
|
||||
expect(snapshot({ a: 1 })).not.toBe(snapshot({ a: 2 }))
|
||||
})
|
||||
|
||||
it('focuses a control by its id, making a non-control focusable first', () => {
|
||||
document.body.innerHTML = '<input id="field-name"><div id="field-members"></div>'
|
||||
expect(focusField('field', 'name')).toBe(true)
|
||||
expect(document.activeElement?.id).toBe('field-name')
|
||||
expect(focusField('field', 'members')).toBe(true)
|
||||
expect(document.getElementById('field-members')?.getAttribute('tabindex')).toBe('-1')
|
||||
expect(document.activeElement?.id).toBe('field-members')
|
||||
expect(focusField('field', 'missing')).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user