test(team): Render-Harness, 151 neue Tests und README
Vorher gab es im Repo kein Muster für Komponententests — @testing-library/react wurde ausschliesslich für renderHook verwendet. test/teamTestUtils.tsx stellt den fehlenden Kontext bereit (Router, MUI-Theme, frischer QueryClient je Test). test/setup.ts registriert jetzt afterEach(cleanup). vitest.config.ts setzt `globals` nicht, deshalb erkennt Testing Library kein globales afterEach und richtet sein automatisches Cleanup nie ein; ohne diese Zeile stapeln sich gerenderte Komponenten und getByRole scheitert ab dem zweiten Test einer Datei. Abgedeckt: Kennzahlenberechnung, Freigabe-, Zurückweisungs-, Anpassungs- und Rückfrageprozess, lokale Persistenz samt Schemaversion und Demo-Reset, Badge-Familie, Vorgangs- und Agentenkarte, Aufgaben-Aktivierung, Einstellungsvalidierung und die Position des Navigationseintrags. Die Tests haben fünf echte Mängel aufgedeckt, alle in diesem Commit behoben: - AgentAvatar hatte keinen zugänglichen Namen. MUI reicht `alt` nur an den img-Slot weiter, und ohne `src` rendert Avatar gar kein <img> — der Wert landete nirgends im DOM. Jetzt role="img" + aria-label direkt am Element. - WorkItemCard verschluckte objectLabel, wenn keine objectId gesetzt war. Genau dort steht bei zuordnungsfreien Vorgängen die entscheidende Einordnung. - aria-current rendert nicht mehr "false", sondern entfällt. - AgentChannelBadge war auf `string` statt AgentChannelType typisiert. 414 Tests grün (vorher 263), Build grün, ESLint über den Property-On-Code sauber, check:tokens unverändert bei 2249. README ersetzt das unveränderte Vite-Template durch Startanleitung und die Architekturentscheidungen samt bekannter Altlasten. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
78e2dab655
commit
a7e05fb7f0
6 files changed
+539
-64
No files matched your search
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Property On — Position und Struktur des Navigationseintrags (§3.3, §3.4).
|
||||
*
|
||||
* Die Spezifikation ist hier wörtlich: «Teamübersicht» steht direkt unter
|
||||
* «Meine Objekte» und oberhalb von «Reminder Manager». Eine spätere Umsortierung
|
||||
* der Navigation würde das still brechen — dieser Test hält es fest.
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { WORKSPACE_CONFIG, getPageNameFromPath } from '../appShellConfig'
|
||||
import { WorkspaceType } from '../../../domain/enums'
|
||||
import { ROUTES } from '../../../lib/constants'
|
||||
|
||||
const supplyNav = WORKSPACE_CONFIG[WorkspaceType.SUPPLY].navItems
|
||||
|
||||
describe('Navigationseintrag «Teamübersicht»', () => {
|
||||
it('steht direkt zwischen «Meine Objekte» und «Reminder Manager»', () => {
|
||||
const labels = supplyNav.map(item => item.label)
|
||||
const objekte = labels.indexOf('Meine Objekte')
|
||||
const team = labels.indexOf('Teamübersicht')
|
||||
const reminder = labels.indexOf('Reminder Manager')
|
||||
|
||||
expect(objekte).toBeGreaterThanOrEqual(0)
|
||||
expect(team).toBe(objekte + 1)
|
||||
expect(reminder).toBe(team + 1)
|
||||
})
|
||||
|
||||
it('führt auf den Basispfad des Funktionsbereichs', () => {
|
||||
const team = supplyNav.find(item => item.label === 'Teamübersicht')
|
||||
expect(team?.path).toBe(ROUTES.SUPPLY.TEAM)
|
||||
})
|
||||
|
||||
it('trägt die drei Subreiter in verbindlicher Reihenfolge', () => {
|
||||
const team = supplyNav.find(item => item.label === 'Teamübersicht')
|
||||
expect(team?.children?.map(c => c.label)).toEqual([
|
||||
'Personalverwaltung',
|
||||
'Bearbeitungsverlauf',
|
||||
'Kanäle & Systeme',
|
||||
])
|
||||
})
|
||||
|
||||
it('verweist mit jedem Subreiter auf einen Unterpfad der Teamübersicht', () => {
|
||||
const team = supplyNav.find(item => item.label === 'Teamübersicht')
|
||||
for (const child of team?.children ?? []) {
|
||||
expect(child.path.startsWith(`${ROUTES.SUPPLY.TEAM}/`)).toBe(true)
|
||||
}
|
||||
})
|
||||
|
||||
it('ist der einzige Hauptreiter mit Subreitern — sonst wäre die Sidebar uneinheitlich', () => {
|
||||
const withChildren = supplyNav.filter(item => (item.children?.length ?? 0) > 0)
|
||||
expect(withChildren.map(item => item.label)).toEqual(['Teamübersicht'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('Seitentitel aus dem Pfad', () => {
|
||||
it('löst Haupt- und Subreiter über die Navigation auf', () => {
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM)).toBe('Teamübersicht')
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_PERSONNEL)).toBe('Personalverwaltung')
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_HISTORY)).toBe('Bearbeitungsverlauf')
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_CONNECTIONS)).toBe('Kanäle & Systeme')
|
||||
})
|
||||
|
||||
it('fängt Deep-Links ab, statt in den Segment-Fallback zu fallen', () => {
|
||||
// Ohne eigene Regel ergäbe der Fallback «Erledigte auftraege» bzw. «Ferdi».
|
||||
expect(getPageNameFromPath(`${ROUTES.SUPPLY.TEAM_PERSONNEL}/ferdi/aufgaben`)).toBe('Personalblatt')
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_HISTORY_DONE)).toBe('Bearbeitungsverlauf')
|
||||
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_HISTORY_PENDING)).toBe('Bearbeitungsverlauf')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user