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:
Jakub Zych
2026-09-27 17:53:57 +02:00
parent 8259a456bb
commit 1c2a66df45
61 changed files with 4299 additions and 91 deletions

View File

@@ -0,0 +1,39 @@
import { describe, expect, it } from 'vitest'
import {
controllerIdFromParams,
controllerIdFromPath,
controllerPath,
parseControllerId,
pluginKey,
} from '../../src/app/controllerRoutes'
describe('controller routes (D-10)', () => {
it('parses a three-segment controller id', () => {
expect(parseControllerId('acme.demo.widgets')).toEqual({ vendor: 'acme', plugin: 'demo', controller: 'widgets' })
expect(parseControllerId('a_b.c-d.E9')).toEqual({ vendor: 'a_b', plugin: 'c-d', controller: 'E9' })
})
it.each(['', 'acme.demo', 'acme.demo.widgets.extra', 'acme..widgets', 'acme.demo.wid gets', 'acme/demo/widgets', '../x.y.z'])(
'rejects %j',
(id) => {
expect(parseControllerId(id)).toBeNull()
expect(controllerPath(id)).toBeNull()
expect(pluginKey(id)).toBeNull()
},
)
it('maps ids and paths both ways', () => {
expect(controllerPath('acme.demo.widgets')).toBe('/acme/demo/widgets')
expect(controllerIdFromParams({ vendor: 'acme', plugin: 'demo', controller: 'widgets' })).toBe('acme.demo.widgets')
expect(controllerIdFromPath('/acme/demo/widgets')).toBe('acme.demo.widgets')
expect(controllerIdFromPath('/acme/demo/widgets/12')).toBe('acme.demo.widgets')
expect(controllerIdFromPath('acme/demo/widgets/')).toBe('acme.demo.widgets')
expect(controllerIdFromPath('/settings')).toBeNull()
expect(controllerIdFromPath('/a/b')).toBeNull()
expect(controllerIdFromPath('/a/b c/d')).toBeNull()
})
it('names the owning plugin of a controller', () => {
expect(pluginKey('acme.demo.widgets')).toBe('acme.demo')
})
})