All checks were successful
Build & Deploy Web / build-and-deploy (push) Successful in 28s
Couvre les surfaces transverses post auth/clients/factures : - billing-states (3) : transitions webhook trial→active, past_due, cancel - billing-quota (2) : Free limite à 2 factures actives, 3e bloquée + toast remonté avec message API (UX bug : onError du dialog masquait l'erreur) - dashboard (2) : zéros au start, +rubis et activity feed après mark-paid - settings (2) : sections visibles + persistence Prénom/Nom après reload Bug isDirty détecté par TDD sur settings : AccountForm/OrganizationForm/ SignatureForm lisaient form.state.isDirty *hors* d'un form.Subscribe, donc le bouton Save ne réagissait jamais aux changements (texte figé sur "Aucune modification"). Fix : wrap le bouton dans form.Subscribe selector=isDirty, même pattern que ManualInvoiceDialog. 36 tests Playwright vert, ~1m20. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import { resetDb } from './helpers/api'
|
|
|
|
/**
|
|
* Scénarios /parametres : forms account + organization + signature.
|
|
*
|
|
* Chaque form est isolé (son propre Save button). On valide la
|
|
* persistence après reload page — pas juste l'UI optimiste.
|
|
*/
|
|
|
|
async function signupAndOnboard(page: import('@playwright/test').Page) {
|
|
const email = `set+${Date.now()}@rubis.test`
|
|
await page.goto('/signup')
|
|
await page.getByLabel(/Prénom \/ Nom/i).fill('Settings Test')
|
|
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 Settings')
|
|
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 })
|
|
}
|
|
|
|
test.describe('Settings', () => {
|
|
test.beforeEach(async () => {
|
|
await resetDb()
|
|
})
|
|
|
|
test('page /parametres affiche les sections principales', async ({ page }) => {
|
|
await signupAndOnboard(page)
|
|
await page.goto('/parametres')
|
|
|
|
await expect(page.getByRole('heading', { name: /paramètres/i })).toBeVisible()
|
|
|
|
// Les sections AccountForm, OrganizationForm, SignatureForm sont
|
|
// toutes visibles (rendues par /parametres). Le scroll est long mais
|
|
// tous les labels sont dans le DOM dès le mount.
|
|
await expect(page.getByText(/^compte$/i).first()).toBeVisible()
|
|
await expect(page.getByText(/^entreprise$/i).first()).toBeVisible()
|
|
await expect(page.getByText(/signature email/i).first()).toBeVisible()
|
|
})
|
|
|
|
test('modifier "Prénom et nom" → toast + persistence après reload', async ({
|
|
page,
|
|
}) => {
|
|
await signupAndOnboard(page)
|
|
await page.goto('/parametres')
|
|
|
|
const fullNameInput = page.getByLabel(/^Prénom et nom$/i)
|
|
await expect(fullNameInput).toBeVisible({ timeout: 5_000 })
|
|
|
|
// L'initial du onboarding était "Settings Test"
|
|
await expect(fullNameInput).toHaveValue('Settings Test')
|
|
|
|
await fullNameInput.fill('Pierre Modifié')
|
|
|
|
// Le bouton passe de "Aucune modification" à "Enregistrer"
|
|
const saveButton = page.getByRole('button', { name: /^enregistrer$/i }).first()
|
|
await saveButton.click()
|
|
|
|
// Confirmation : le bouton revient à "Aucune modification" après save
|
|
await expect(
|
|
page.getByRole('button', { name: /aucune modification/i }).first(),
|
|
).toBeVisible({ timeout: 5_000 })
|
|
|
|
// Reload : la valeur persiste
|
|
await page.reload()
|
|
await expect(page.getByLabel(/^Prénom et nom$/i)).toHaveValue('Pierre Modifié')
|
|
})
|
|
})
|