- Add shadcn Form helpers (Form, FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription) on top of react-hook-form's Controller - Add shadcn Select wrapping @radix-ui/react-select with Trigger / Content / Item / Value, lucide chevron + check icons - Profile form now wraps fields in <Form>...<FormField> blocks; gender and activityLevel use the new Select with placeholder, the rest use Input; validation errors land in <FormMessage> per field automatically Playwright config: - webServer is now an array — Playwright boots both api (:4000) and web (:3000) before the suite, so server actions that proxy to API_URL work in CI/local - profile.spec.ts updated for the new flow: post-signup goes through /welcome to accept the medical disclaimer, then through Select primitives via combobox click + role=option for Sesso and Livello di attività Verified: pnpm test:e2e — 4/4 specs pass (home + 2 auth + profile). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
50 lines
2.2 KiB
TypeScript
50 lines
2.2 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
||
|
||
function uniqueEmail(): string {
|
||
const ts = Date.now();
|
||
const rand = Math.floor(Math.random() * 1e6);
|
||
return `e2e-profile-${ts}-${rand}@ketopath.test`;
|
||
}
|
||
|
||
test('profile flow — submit returns BMR/TDEE for the Michele PRD persona', async ({ page }) => {
|
||
const email = uniqueEmail();
|
||
const password = 'Password!123';
|
||
const name = 'Michele E2E';
|
||
|
||
// Sign-up gives us an authenticated session
|
||
await page.goto('/sign-up');
|
||
await page.getByLabel('Nome').fill(name);
|
||
await page.getByLabel('Email').fill(email);
|
||
await page.getByLabel('Password').fill(password);
|
||
await page.getByRole('button', { name: 'Crea account' }).click();
|
||
await page.waitForURL('/');
|
||
|
||
// Open profile from home — first time we'll be redirected through /welcome
|
||
await page.getByRole('link', { name: 'Completa il tuo profilo' }).click();
|
||
await page.waitForURL('/welcome');
|
||
|
||
// Accept the medical disclaimer (3 mandatory checkboxes + submit)
|
||
await page.getByLabel(/Confermo di essere maggiorenne/).check();
|
||
await page.getByLabel(/Dichiaro di non avere condizioni mediche escludenti/).check();
|
||
await page.getByLabel(/Accetto che KetoPath non sostituisce/).check();
|
||
await page.getByRole('button', { name: 'Accetto e proseguo' }).click();
|
||
await page.waitForURL('/profile');
|
||
|
||
// Fill the form with the "Michele" PRD persona values
|
||
await page.getByLabel('Età').fill('49');
|
||
await page.getByLabel('Sesso').click();
|
||
await page.getByRole('option', { name: 'Maschio' }).click();
|
||
await page.getByLabel('Altezza (cm)').fill('170');
|
||
await page.getByLabel('Peso iniziale (kg)').fill('76');
|
||
await page.getByLabel('Peso attuale (kg)').fill('76');
|
||
await page.getByLabel('Peso obiettivo (kg)').fill('70');
|
||
await page.getByLabel('Livello di attività').click();
|
||
await page.getByRole('option', { name: /Sedentario/ }).click();
|
||
await page.getByRole('button', { name: 'Salva profilo' }).click();
|
||
|
||
// BMR/TDEE summary panel becomes visible after a successful save
|
||
await expect(page.getByText('Calcolo personalizzato')).toBeVisible();
|
||
await expect(page.getByText('1583 kcal')).toBeVisible(); // BMR Michele
|
||
await expect(page.getByText('1899 kcal')).toBeVisible(); // TDEE = 1582.5 × 1.2
|
||
});
|