import { expect, test } from '@playwright/test'; /** * Recette R2 (plan de releases) : demande gardien → approbation → OT → * intervention → bilan codé → clôture → suivi demandeur ; génération du * préventif du mois (idempotente) ; compteur croissant. */ const suffix = Date.now().toString(36); test('recette R2 : demande → OT → bilan codé → clôture → suivi demandeur', async ({ page, }) => { // 1 · Karim (demandeur) signale depuis l'app await page.goto('/connexion'); await page.getByRole('button', { name: /Karim Doukkali/ }).click(); await expect(page.getByRole('heading', { name: 'Mes signalements' })).toBeVisible(); await page.getByRole('link', { name: /Demandes/ }).click(); await page.getByRole('button', { name: '+ Signaler' }).click(); await page.getByLabel('Équipement *').selectOption({ index: 1 }); await page.getByLabel('Décrivez le problème *').fill(`E2E ${suffix} — porte qui claque très fort`); await page.getByRole('button', { name: 'Envoyer le signalement' }).click(); await expect(page.getByRole('cell', { name: new RegExp(suffix) })).toBeVisible(); // 2 · Salma (dispatcher) approuve → OT créé, assigné à Ahmed await page.locator('.compte').click(); await page.getByRole('menuitem', { name: /Salma Idrissi/ }).click(); await page.getByRole('link', { name: /Demandes/ }).click(); await page.getByRole('cell', { name: new RegExp(suffix) }).click(); await page.getByLabel('Assigner à').selectOption({ index: 1 }); // Ahmed Benali await page.getByRole('button', { name: "Approuver → créer l'OT" }).click(); // → fiche OT await expect(page.getByRole('heading', { name: new RegExp(suffix) })).toBeVisible(); await expect(page.locator('.entete-page .st')).toHaveText('Ouvert'); // 3 · Démarrer, tenter de clôturer (bloqué : bilan), remplir le bilan, clôturer await page.getByRole('button', { name: 'Démarrer' }).click(); await expect(page.locator('.entete-page .st')).toHaveText('En cours'); const boutonCloture = page.getByRole('button', { name: "Clôturer l'intervention" }); await expect(boutonCloture).toBeDisabled(); // garde visible dans l'UI await expect(page.locator('.avertissement')).toContainText('bilan incomplet'); await page.getByLabel(/État des portes/).selectOption({ label: 'Fonctionnement normal' }); await page.getByLabel(/Action réalisée/).selectOption({ label: 'Réglage' }); await page.getByLabel(/Élément concerné/).selectOption({ label: 'Portes' }); await expect(boutonCloture).toBeEnabled(); await boutonCloture.click(); await expect(page.locator('.entete-page .st')).toHaveText('Terminé'); // 4 · Karim suit : sa demande est Résolue await page.locator('.compte').click(); await page.getByRole('menuitem', { name: /Karim Doukkali/ }).click(); await page.getByRole('link', { name: /Demandes/ }).click(); const ligne = page.locator('tr', { hasText: suffix }); await expect(ligne.locator('.st')).toHaveText('Résolue'); }); test('préventif : générer le mois — puis regénérer ne double rien', async ({ page }) => { await page.goto('/connexion'); await page.getByRole('button', { name: /Yasmine Alaoui/ }).click(); await page.getByRole('link', { name: 'Préventif' }).click(); await expect(page.getByRole('heading', { name: 'Préventif' })).toBeVisible(); await expect(page.getByText('Essai du parachute')).toBeVisible(); await page.getByRole('button', { name: /Générer la grille de/ }).click(); await expect(page.locator('.gen-info')).toContainText('regénérer ne double rien'); // Second appel : 0 créé await page.getByRole('button', { name: /Générer la grille de/ }).click(); await expect(page.locator('.gen-info')).toContainText('0 OT créés'); }); test('urgence « personne bloquée » : interrupteur → chip topbar + bandeau + tête de liste', async ({ page, }) => { await page.goto('/connexion'); await page.getByRole('button', { name: /Salma Idrissi/ }).click(); await page.getByRole('link', { name: /Ordres de travail/ }).click(); await page.getByRole('button', { name: '+ Nouvel OT' }).click(); await page.getByLabel('Objet *').fill(`E2E ${suffix} — personne bloquée cage B`); await page.getByLabel('Équipement *').selectOption({ index: 1 }); await page.getByRole('switch', { name: 'Personne bloquée' }).click(); await page.getByRole('button', { name: "Créer l'OT (statut Ouvert)" }).click(); await expect(page.getByRole('heading', { name: new RegExp(suffix) })).toBeVisible(); // chip topbar (pulse) présent et bandeau sur le tableau de bord await expect(page.locator('.topbar .chip-urgence')).toContainText('personne'); await page.getByRole('link', { name: 'Tableau de bord' }).click(); await expect(page.locator('.bandeau-urgence').first()).toBeVisible(); // tête de liste OT await page.getByRole('link', { name: /Ordres de travail/ }).click(); await expect(page.locator('tbody tr').first()).toHaveClass(/ligne-bloque/); // nettoyage : annuler l'OT d'urgence créé (motif via prompt) await page.locator('tbody tr').first().click(); page.once('dialog', (d) => d.accept('Test e2e — nettoyage')); await page.getByRole('button', { name: 'Annuler', exact: true }).click(); await expect(page.locator('.entete-page .st')).toHaveText('Annulé'); }); test('compteurs : relevé croissant accepté, régression refusée', async ({ page }) => { await page.goto('/connexion'); await page.getByRole('button', { name: /Ahmed Benali/ }).click(); await page.getByRole('link', { name: 'Ascenseurs' }).click(); await page.getByRole('cell', { name: 'A1', exact: true }).click(); await page.getByRole('button', { name: 'Compteurs' }).click(); await expect(page.getByRole('heading', { name: /Compteurs — Ascenseur A1/ })).toBeVisible(); const saisie = page.getByLabel('Nouveau relevé — Heures de marche'); await saisie.fill('99999999'); await page.getByRole('button', { name: 'Enregistrer le relevé' }).first().click(); await expect(page.locator('.chrono').first()).toContainText('99 999 999'); await saisie.fill('12'); await page.getByRole('button', { name: 'Enregistrer le relevé' }).first().click(); await expect(page.locator('.erreur-form')).toContainText('ne redescend pas'); });