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>
86 lines
3.5 KiB
TypeScript
86 lines
3.5 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import { resetDb } from './helpers/api'
|
|
|
|
/**
|
|
* Scénarios dashboard : KPIs à zéro au start, bump après actions.
|
|
*
|
|
* Les calculs des KPIs sont testés par les tests japa functional
|
|
* (dashboard.spec.ts) — ici on valide la chaîne SPA → API → render
|
|
* sur la page d'accueil.
|
|
*/
|
|
|
|
async function signupAndOnboard(page: import('@playwright/test').Page) {
|
|
const email = `dash+${Date.now()}@rubis.test`
|
|
await page.goto('/signup')
|
|
await page.getByLabel(/Prénom \/ Nom/i).fill('Dashboard 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 Dashboard')
|
|
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('Dashboard', () => {
|
|
test.beforeEach(async () => {
|
|
await resetDb()
|
|
})
|
|
|
|
test('zéros au start : 0 rubis, "Pas encore d\'activité"', async ({ page }) => {
|
|
await signupAndOnboard(page)
|
|
await page.goto('/')
|
|
|
|
// RubisHero : "0 rubis gagnés ce mois"
|
|
await expect(page.getByText(/0\s+rubis/i).first()).toBeVisible({ timeout: 10_000 })
|
|
|
|
// Activity feed vide
|
|
await expect(
|
|
page.getByText(/pas encore d'activité|importez votre première facture/i).first(),
|
|
).toBeVisible()
|
|
})
|
|
|
|
test('après mark-paid : rubis += 1 + activity contient l\'event', async ({
|
|
page,
|
|
}) => {
|
|
await signupAndOnboard(page)
|
|
|
|
// 1. Créer client + facture
|
|
await page.getByRole('button', { name: /^saisir$/i }).first().click()
|
|
const combobox = page.getByPlaceholder(/rechercher.*créer un client/i)
|
|
await combobox.fill('Dashboard Client')
|
|
await page.getByRole('button', { name: /créer le client.*dashboard client/i }).click()
|
|
await page.getByLabel(/email du client/i).fill('client@dashboard.test')
|
|
await page.getByLabel(/N° de facture/i).fill('F-DASH-001')
|
|
await page.getByLabel(/Montant TTC/i).fill('500')
|
|
await page.getByLabel(/Plan de relance/i).click()
|
|
await page.getByRole('option').first().click()
|
|
await page.getByRole('button', { name: /^créer la facture$/i }).click()
|
|
await expect(page.getByText(/facture créée/i)).toBeVisible({ timeout: 5_000 })
|
|
|
|
// 2. Aller sur la facture, mark-paid
|
|
await page.goto('/factures')
|
|
await page.getByText('F-DASH-001').first().click()
|
|
await page.getByRole('button', { name: /marquer encaissée/i }).click()
|
|
await expect(page.getByText(/encaissée.*rubis/i)).toBeVisible({ timeout: 5_000 })
|
|
|
|
// 3. Sur le dashboard, rubis count = 1 (création) + 1 (mark-paid) = 2 rubis
|
|
// Note : la création d'une facture saisie manuelle pose rubisEarned=1
|
|
// et le mark-paid bump encore +1
|
|
await page.goto('/')
|
|
// Le compteur RubisHero affiche "X rubis gagnés" et la sidebar aussi
|
|
await expect(page.getByText(/[1-2]\s+rubis/i).first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
// 4. Activity feed contient l'event "Facture F-DASH-001 marquée encaissée"
|
|
await expect(page.getByText(/F-DASH-001/).first()).toBeVisible({
|
|
timeout: 5_000,
|
|
})
|
|
})
|
|
})
|