import { expect, test } from '@playwright/test' import { loginAs } from '../helpers/loginAs' import { SidebarComponent } from '../helpers/pages/SidebarComponent' import { ALL_ADMIN_LINKS, type PersonaKey, getPersona, personas } from '../_fixtures/personas' /** * Test strategique : la matrice persona <-> liens admin visibles. * * Valide que `SidebarProvider` (back) + `useSidebar` (front) filtrent bien * les items admin selon les permissions RBAC de chaque user. * * Regle d'evolution : ajouter une permission ou un persona = 1 ligne a * modifier dans `personas.ts` et cote back (`SeedE2ECommand`) + `sidebar.php`. * Ce fichier ne bouge pas. */ test.describe('Sidebar visibility', () => { const personaKeys: PersonaKey[] = [ 'super-admin', 'user-full', 'user-readonly', 'user-users-only', 'user-audit-only', 'user-nothing', ] for (const key of personaKeys) { const persona = getPersona(key) test(`${persona.key} ne voit que ses liens admin autorises`, async ({ page, context }) => { await loginAs(context, persona.key) await page.goto('/') const sidebar = new SidebarComponent(page) // Attente semantique : on ancre sur un lien toujours present pour // tout user authentifie (Mon compte > Tableau de bord). Remplace // `networkidle` qui est reconnu instable en CI (SPAs avec polling // ou HMR peuvent ne jamais quitter cet etat). await expect(sidebar.accountDashboardLink()).toBeVisible({ timeout: 10000 }) for (const link of ALL_ADMIN_LINKS) { const locator = sidebar.adminLink(link) const shouldBeVisible = persona.expectedAdminLinks.includes(link) if (shouldBeVisible) { await expect( locator, `${persona.key} doit voir le lien /admin/${link}`, ).toBeVisible() } else { await expect( locator, `${persona.key} ne doit PAS voir le lien /admin/${link}`, ).toHaveCount(0) } } }) } test('user-nothing voit toujours le dashboard et le logout (section Mon compte sans permission)', async ({ page, context, }) => { // La section "Mon compte" n'est gardee par aucune permission : tout user // authentifie voit le dashboard et peut se deconnecter. Ce test protege // contre une regression qui mettrait un gate RBAC par inadvertance // dessus — ca bloquerait le logout de users sans permissions. await loginAs(context, 'user-nothing') await page.goto('/') const sidebar = new SidebarComponent(page) // Meme strategie que ci-dessus : ancrage semantique plutot que // `networkidle` pour eviter les faux timeouts en CI. await expect(sidebar.accountDashboardLink()).toBeVisible({ timeout: 10000 }) await expect(sidebar.logoutLink()).toBeVisible() }) test('la liste des personas dans personas.ts couvre toutes les combinaisons admin attendues', () => { // Test meta : si quelqu'un ajoute un persona dans personas.ts sans le // seeder cote back (SeedE2ECommand), le test sidebar pour ce persona // echouera (loginAs 401). Ce test rappelle la coherence attendue. expect(Object.keys(personas)).toEqual(personaKeys) }) })