Aufgaben, Systeme und Kanäle werden alle drei als Liste geführt und ab jetzt auch gleich bearbeitet: anlegen, ändern, entfernen, zu- und abschalten — dort, wo man sie sieht. Die Maske und die drei Listengriffe stehen einmal zentral statt dreimal je Reiter; sonst unterscheiden sie sich nach der ersten Korrektur. - AgentEntityDialog: eine Maske für alle drei Entitäten, über den React- Schlüssel je Eintrag neu aufgebaut statt über einen Effekt zurückgesetzt - agentEntityEditing: upsertById, removeById, newEntityId als reine Funktionen - Systeme sind über Provider, Service und Hook schreibbar (saveSystems) und tragen neu einen Aktiv-Schalter - Systemreiter: eine einzige Liste statt «Lesende»/«Schreibende Systemzugänge», kein Einleitungsbalken mehr; Aktiv, Zugriff und Verbindung stehen je Eintrag - Thomas steht als «Agentenverwalter» in der Navigation, zählt aber nicht als sechster Agent in Sitzungszimmer, Auslastung und Begrüssung - Chatverlauf scrollt in sich, ohne die Seite springen zu lassen Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
4.6 KiB
TypeScript
104 lines
4.6 KiB
TypeScript
/**
|
|
* Property On — Position und Struktur des Navigationseintrags «Meine Agenten».
|
|
*
|
|
* Seit Runde 4 ist «Meine Agenten» der einzige Eintrag mit Unterpunkten, und
|
|
* diese Unterpunkte sind die fünf digitalen Mitarbeitenden in verbindlicher
|
|
* Reihenfolge. Eine spätere Umsortierung 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 { HOME_NAV_LABEL, MY_AGENTS_LABEL, ROUTES } from '../../../lib/constants'
|
|
import { AGENT_NAV_ENTRIES } from '../../../lib/agentWorkspaces'
|
|
|
|
const supplyNav = WORKSPACE_CONFIG[WorkspaceType.SUPPLY].navItems
|
|
|
|
describe('Hauptnavigation der Verwaltung', () => {
|
|
it('führt «Übersicht» nicht mehr (Runde 5, §2.1)', () => {
|
|
expect(supplyNav.map(item => item.label)).not.toContain('Übersicht')
|
|
expect(supplyNav.map(item => item.path)).not.toContain(ROUTES.SUPPLY.LEGACY_DASHBOARD)
|
|
})
|
|
|
|
it('beginnt mit der «Startseite» und führt sie nur einmal', () => {
|
|
expect(supplyNav[0]?.label).toBe(HOME_NAV_LABEL)
|
|
expect(supplyNav[0]?.path).toBe(ROUTES.SUPPLY.PROPERTIES)
|
|
expect(supplyNav.filter(item => item.path === ROUTES.SUPPLY.PROPERTIES)).toHaveLength(1)
|
|
})
|
|
|
|
it('startet den Arbeitsbereich auf der Startseite', () => {
|
|
expect(WORKSPACE_CONFIG[WorkspaceType.SUPPLY].firstPath).toBe(ROUTES.SUPPLY.PROPERTIES)
|
|
})
|
|
})
|
|
|
|
describe('Navigationseintrag «Meine Agenten»', () => {
|
|
it('steht direkt unter der «Startseite»', () => {
|
|
const labels = supplyNav.map(item => item.label)
|
|
const startseite = labels.indexOf(HOME_NAV_LABEL)
|
|
const agenten = labels.indexOf(MY_AGENTS_LABEL)
|
|
|
|
expect(startseite).toBeGreaterThanOrEqual(0)
|
|
expect(agenten).toBe(startseite + 1)
|
|
})
|
|
|
|
it('führt auf den Basispfad des Funktionsbereichs', () => {
|
|
const agenten = supplyNav.find(item => item.label === MY_AGENTS_LABEL)
|
|
expect(agenten?.path).toBe(ROUTES.SUPPLY.TEAM)
|
|
})
|
|
|
|
it('trägt Thomas zuoberst und darunter die fünf in verbindlicher Reihenfolge', () => {
|
|
const agenten = supplyNav.find(item => item.label === MY_AGENTS_LABEL)
|
|
expect(agenten?.children?.map(c => c.label)).toEqual(['Thomas', 'Ferdi', 'Bruno', 'Livia', 'Nora', 'Sina'])
|
|
})
|
|
|
|
it('gibt jedem Agenten Porträt-ID und Funktionsbezeichnung mit', () => {
|
|
const agenten = supplyNav.find(item => item.label === MY_AGENTS_LABEL)
|
|
for (const child of agenten?.children ?? []) {
|
|
expect(child.agentId).toBeTruthy()
|
|
expect(child.role).toBeTruthy()
|
|
}
|
|
})
|
|
|
|
it('verweist mit jedem Agenten auf eine eigene Seite', () => {
|
|
const agenten = supplyNav.find(item => item.label === MY_AGENTS_LABEL)
|
|
const paths = agenten?.children?.map(c => c.path) ?? []
|
|
expect(paths).toEqual(AGENT_NAV_ENTRIES.map(a => a.path))
|
|
expect(new Set(paths).size).toBe(paths.length)
|
|
})
|
|
|
|
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([MY_AGENTS_LABEL])
|
|
})
|
|
|
|
it('führt Reto und Lea nicht mehr', () => {
|
|
const labels = supplyNav.flatMap(item => [item.label, ...(item.children ?? []).map(c => c.label)])
|
|
expect(labels).not.toContain('Reto')
|
|
expect(labels).not.toContain('Lea')
|
|
})
|
|
})
|
|
|
|
describe('Seitentitel aus dem Pfad', () => {
|
|
it('löst Haupt- und Agentenreiter über die Navigation auf', () => {
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.PROPERTIES)).toBe(HOME_NAV_LABEL)
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM)).toBe(MY_AGENTS_LABEL)
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.AGENT_FERDI)).toBe('Ferdi')
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.AGENT_BRUNO)).toBe('Bruno')
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.AGENT_LIVIA)).toBe('Livia')
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.AGENT_NORA)).toBe('Nora')
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.AGENT_SINA)).toBe('Sina')
|
|
})
|
|
|
|
it('trägt die alten Unterseitenpfade bis zur Umleitung unter «Meine Agenten»', () => {
|
|
// Ohne eigene Regel ergäbe der Fallback «Personalverwaltung» bzw. «Erledigte auftraege».
|
|
expect(getPageNameFromPath(`${ROUTES.SUPPLY.TEAM_PERSONNEL}/ferdi/aufgaben`)).toBe(MY_AGENTS_LABEL)
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_HISTORY_DONE)).toBe(MY_AGENTS_LABEL)
|
|
expect(getPageNameFromPath(ROUTES.SUPPLY.TEAM_CONNECTIONS)).toBe(MY_AGENTS_LABEL)
|
|
})
|
|
|
|
it('erkennt die Objekt-Detailroute', () => {
|
|
expect(getPageNameFromPath(`${ROUTES.SUPPLY.PROPERTIES}/prop-001`)).toBe('Objekt Detail')
|
|
})
|
|
})
|