import { test, expect } from '@playwright/test' import { resetDb } from './helpers/api' /** * Scénarios facture — saisie manuelle via dialog. * * Le dialog combine combobox client async, DatePicker custom, Radix Select * (échéance + plan), Input montant. On vise le happy path UI ; * les edge cases (numéro unique, quota Free 2, cross-org, payload * incomplet) sont déjà couverts par les tests japa functional/unit. */ async function signupAndOnboard(page: import('@playwright/test').Page, tag = 'fac') { const email = `${tag}+${Date.now()}@rubis.test` await page.goto('/signup') await page.getByLabel(/Prénom \/ Nom/i).fill('Test User') await page.getByLabel(/Email professionnel/i).fill(email) await page.getByLabel(/Mot de passe/i).fill('motdepasse-fort-123') await page.getByRole('button', { name: /créer mon compte/i }).click() await page.waitForURL(/\/onboarding\/compte/, { timeout: 10_000 }) await page.getByRole('button', { name: /continuer/i }).click() await page.waitForURL(/\/onboarding\/entreprise/) await page.getByLabel(/nom de l'entreprise/i).fill('Atelier Test') await page.getByRole('button', { name: /continuer/i }).click() await page.waitForURL(/\/onboarding\/signature/) await page.getByRole('button', { name: /terminer/i }).click() await page.waitForURL('/', { timeout: 10_000 }) return { email } } async function createClientViaUI( page: import('@playwright/test').Page, name: string, email: string, ) { await page.goto('/clients') await page.getByRole('button', { name: /nouveau client/i }).first().click() await page.getByLabel(/^Nom du client$/i).fill(name) await page.getByLabel(/^Email du contact$/i).fill(email) await page.getByRole('button', { name: /^créer le client$/i }).click() await expect(page.getByText(name).first()).toBeVisible({ timeout: 5_000 }) } test.describe('Factures — saisie manuelle via dialog', () => { test.beforeEach(async () => { await resetDb() }) test('crée une facture liée à un client existant + apparaît dans /factures', async ({ page, }) => { await signupAndOnboard(page, 'fac-manual') // 1. Prérequis : un client en DB await createClientViaUI(page, 'Boulangerie Test', 'compta@boulangerie.test') // 2. Ouvrir le dialog "+ Saisir" depuis le header desktop await page.getByRole('button', { name: /^saisir$/i }).first().click() await expect(page.getByRole('dialog')).toBeVisible() // 3. Combobox client — taper le nom puis sélectionner l'option dans // la dropdown (recherche async côté API). const combobox = page.getByPlaceholder(/rechercher.*créer un client/i) await combobox.fill('Boulangerie') // Attendre que l'option remontée par l'API apparaisse await expect(page.getByRole('option', { name: /Boulangerie Test/i })).toBeVisible({ timeout: 5_000, }) await page.getByRole('option', { name: /Boulangerie Test/i }).click() // 4. Numéro de facture await page.getByLabel(/N° de facture/i).fill('F-E2E-001') // 5. Montant TTC (en euros, le form convertit en cents) await page.getByLabel(/Montant TTC/i).fill('1240') // 6. Plan (Radix Select) — on prend le 1er disponible await page.getByLabel(/Plan de relance/i).click() // L'item Radix s'affiche via Portal — on cible par rôle option await page.getByRole('option').first().click() // 7. Submit await page.getByRole('button', { name: /^créer la facture$/i }).click() // 8. Le dialog se ferme + redirection vers /factures (route handler du form) // ou bien rester sur la page courante. On navigue manuellement pour // vérifier la persistence. await page.goto('/factures') await expect(page.getByText('F-E2E-001').first()).toBeVisible({ timeout: 10_000 }) await expect(page.getByText('Boulangerie Test').first()).toBeVisible() }) test('liste vide → empty state visible', async ({ page }) => { await signupAndOnboard(page, 'fac-empty') await page.goto('/factures') // Empty state avec un texte parlant await expect( page.getByText(/aucune facture|pas encore.*facture/i).first(), ).toBeVisible({ timeout: 5_000 }) }) })