import { expect, test } from '@playwright/test'; /** * Recette R1 (plan de releases) : créer un site → un ascenseur → ses organes * → imprimer l'étiquette QR → inviter un technicien (activation incluse). */ const suffix = Date.now().toString(36); test('recette R1 complète, de la création du site à l’activation de l’invité', async ({ page, }) => { // Connexion démo (Administrateur — création tous azimuts) await page.goto('/connexion'); await page.getByRole('button', { name: /Yasmine Alaoui/ }).click(); await expect(page.getByRole('heading', { name: 'Tableau de bord' })).toBeVisible(); // 1 · Sites : le parc seedé est là, on crée un site await page.getByRole('link', { name: 'Sites' }).click(); await expect(page.getByRole('cell', { name: /Tour Atlas/ })).toBeVisible(); await page.getByRole('button', { name: '+ Nouveau site' }).click(); await page.getByLabel('Nom du site *').fill(`Site E2E ${suffix}`); await page.getByLabel('Ville').fill('Casablanca'); await page.getByRole('button', { name: 'Créer le site' }).click(); // → fiche du site créé ; on lui ajoute une zone await expect(page.getByRole('heading', { name: `Site E2E ${suffix}` })).toBeVisible(); await page.getByRole('button', { name: '+ Ajouter un emplacement' }).click(); await page.getByLabel('Nom de la zone *').fill(`Hall E2E ${suffix}`); await page.getByRole('button', { name: 'Ajouter', exact: true }).click(); await expect(page.locator('.arbre')).toContainText(`Hall E2E ${suffix}`); // 2 · Nouvel ascenseur avec un organe await page.getByRole('button', { name: '+ Nouvel ascenseur' }).click(); await page.getByLabel('Référence *').fill(`E2E-${suffix}`); await page.getByLabel('Marque *').fill('Otis'); await page.getByLabel('Catégorie *').selectOption({ label: 'Ascenseur électrique' }); await page.getByLabel('Emplacement dans le site *').selectOption({ label: `Hall E2E ${suffix}` }); await page.getByLabel("Type de l'organe 1").selectOption({ label: 'Portes cabine / palières' }); await page.getByLabel("Désignation de l'organe 1").fill('Fermator 40/10'); await page.getByRole('button', { name: "Créer l'ascenseur (QR généré)" }).click(); // → fiche appareil : identité, organe, QR await expect( page.getByRole('heading', { name: new RegExp(`Ascenseur E2E-${suffix}`) }), ).toBeVisible(); await expect(page.getByText('Portes cabine / palières')).toBeVisible(); // 3 · Étiquette QR imprimable await page.getByRole('button', { name: 'Étiquette QR' }).click(); await expect(page.locator('.etiquette')).toContainText(`Ascenseur E2E-${suffix}`); await expect(page.locator('.etiquette .consigne')).toContainText('Scannez ce code'); // 4 · Inviter un technicien → récupérer le lien d'activation await page.getByRole('link', { name: 'Personnes' }).click(); await page.getByRole('button', { name: '+ Inviter' }).click(); await page.getByLabel('Nom complet *').fill('Recrue E2E'); await page.getByLabel('Email professionnel *').fill(`recrue-${suffix}@spelev.ma`); await page.getByLabel('Rôle *').selectOption({ label: 'Technicien' }); await page.getByRole('button', { name: "Envoyer l'invitation" }).click(); const lien = await page.getByTestId('lien-activation').textContent(); expect(lien).toContain('/activation?token='); await page.getByRole('button', { name: 'Fermer' }).click(); await expect(page.getByRole('cell', { name: /Recrue E2E/ })).toBeVisible(); await expect(page.getByText('Invitation envoyée')).toBeVisible(); // 5 · La recrue active son compte via le lien et entre directement await page.locator('.compte').click(); await page.getByRole('menuitem', { name: 'Se déconnecter' }).click(); await page.goto(lien!); await page.getByLabel('Mot de passe (8 caractères minimum)').fill('MotDePasse!123'); await page.getByLabel('Confirmez le mot de passe').fill('MotDePasse!123'); await page.getByRole('button', { name: 'Activer mon compte' }).click(); await expect(page.getByRole('heading', { name: 'Tableau de bord' })).toBeVisible(); await expect(page.locator('.topbar')).toContainText('Recrue E2E'); await expect(page.locator('.topbar')).toContainText('Technicien'); }); test('la matrice pilote l’UI : un technicien voit le parc sans boutons de création', async ({ page, }) => { await page.goto('/connexion'); await page.getByRole('button', { name: /Ahmed Benali/ }).click(); await expect(page.getByRole('heading', { name: 'Tableau de bord' })).toBeVisible(); // Catégories (SETTINGS) absent de sa sidebar ; Ascenseurs accessible await expect(page.locator('.nav')).not.toContainText('Catégories'); await page.getByRole('link', { name: 'Ascenseurs' }).click(); await expect(page.getByRole('cell', { name: 'A1', exact: true })).toBeVisible(); await expect(page.getByRole('button', { name: '+ Nouvel ascenseur' })).toHaveCount(0); // Fiche : statuts visibles, pas de retrait d'organe await page.getByRole('cell', { name: 'A1', exact: true }).click(); await expect(page.getByText('Treuil / machinerie')).toBeVisible(); await expect(page.getByRole('button', { name: /Retirer/ })).toHaveCount(0); });