// @ts-check import { test, expect } from '@playwright/test'; import { loadTestUser } from '../utils/testUser.js'; test.describe('@p0 Profile Account — JIT-PII + greeting (UI save)', () => { test.setTimeout(15000); test('UI save first name → GET ?fields=firstname allowlist only → landing greets with saved name', async ({ page }) => { const user = loadTestUser(); // Sign in await page.context().clearCookies(); await page.goto('/signin', { waitUntil: 'networkidle' }); await page.getByPlaceholder('Username', { exact: true }).fill(user.username); await page.getByPlaceholder('Password', { exact: true }).fill(user.password); await page.getByRole('button', { name: /^Sign In$/ }).click(); await page.waitForURL('**/signin-landing**', { timeout: 15000 }); // Go to Profile (UI form handles required fields & correct casing) await page.goto('/profile', { waitUntil: 'networkidle' }); // Inputs const firstInput = page.getByLabel(/^First Name:$/i).or(page.locator('input').nth(0)); const lastInput = page.getByLabel(/^Last Name:$/i); const emailInput = page.getByLabel(/^Email:$/i); const zipInput = page.getByLabel(/^ZIP Code:$/i); const stateSel = page.getByLabel(/^State:$/i); // Make sure the form is hydrated await expect(firstInput).toBeVisible({ timeout: 10000 }); const oldFirst = await firstInput.inputValue(); // New firstname (unique) const stamp = new Date().toISOString().slice(11,19).replace(/:/g, ''); const newFirst = `E2E${stamp}`; // Keep everything else as-is; only change First Name await firstInput.fill(newFirst); // Submit await page.getByRole('button', { name: /^Save Profile$/i }).click(); // Give the backend a moment, then assert via JIT-PII allowlist const jit = await page.request.get('/api/user-profile?fields=firstname'); expect(jit.status()).toBe(200); const body = await jit.json(); const keys = Object.keys(body || {}); const allowed = new Set(['firstname', 'is_premium', 'is_pro_premium']); expect(keys.every(k => allowed.has(k))).toBeTruthy(); expect(String(body.firstname || '')).toBe(newFirst); // Landing greeting reflects saved name await page.goto('/signin-landing', { waitUntil: 'networkidle' }); const greetRe = new RegExp(`^\\s*Welcome to AptivaAI\\s+${newFirst.replace(/[.*+?^${}()|[\\]\\\\]/g,'\\\\$&')}!\\s*$`); await expect(page.getByRole('heading', { name: greetRe })).toBeVisible({ timeout: 10000 }); // Cleanup: restore old firstname (so we don’t pollute the account) await page.goto('/profile', { waitUntil: 'networkidle' }); await firstInput.fill(oldFirst); await page.getByRole('button', { name: /^Save Profile$/i }).click(); }); });