d6a40e4843
Déconnexion déplacée du menu vers le footer (compte connecté au survol + version). useLogout() appelle clearSession() (reset des stores singletons via onAuthSessionCleared) puis redirige vers /login, sans page /logout intermédiaire.
88 lines
3.6 KiB
TypeScript
88 lines
3.6 KiB
TypeScript
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 })
|
|
// La deconnexion vit dans le footer (rendu sans condition de permission).
|
|
// Le bouton est revele au survol du bloc compte.
|
|
await sidebar.accountBlock().hover()
|
|
await expect(sidebar.logoutButton()).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)
|
|
})
|
|
})
|