import { es } from '@impuestos/i18n'; import { expect, test } from '@playwright/test'; import { readAuditActions } from './db'; /** Flow E3. The trust screen: what we hold, and the two ways to take it back. */ test.describe('profile', () => { test.beforeEach(async ({ page }) => { await page.goto('/es/login'); await page.getByLabel(es['auth.register.email']).fill('maria@demo.local'); await page.getByLabel(es['auth.login.password']).fill('demo-maria-1'); await page.getByRole('button', { name: es['auth.login.submit'] }).click(); await expect(page).toHaveURL(/\/es\/inicio$/); }); test('shows the seeded identity, dependants and the data section', async ({ page }) => { await page.goto('/es/perfil'); await expect(page.getByLabel(es['setup.fullName'])).toHaveValue('Maria Gonzalez'); await expect(page.getByLabel(es['setup.docLabel'])).toHaveValue('4123456-1'); // Base ends in 6, so RULES.md puts her deadline on the 19th. await expect(page.getByText(es['vto.explainer'].replace('{digit}', '6').replace('{day}', '19'))).toBeVisible(); await expect(page.getByText('Lucas Gonzalez')).toBeVisible(); await expect( page.getByRole('heading', { name: es['profile.myData.title'], exact: true }), ).toBeVisible(); await expect(page.getByRole('link', { name: es['profile.myData.export'] })).toBeVisible(); }); test('adds and removes a dependant', async ({ page }) => { await page.goto('/es/perfil'); const name = `Prueba ${Date.now()}`; await page.getByLabel(es['setup.dependents.name'], { exact: true }).fill(name); await page.getByRole('button', { name: es['setup.dependents.add'] }).click(); await expect(page.getByText(name)).toBeVisible(); await page .getByRole('listitem') .filter({ hasText: name }) .getByRole('button', { name: es['common.remove'] }) .click(); await expect(page.getByText(name)).toBeHidden(); expect(readAuditActions('maria@demo.local')).toContain('dependent.create'); expect(readAuditActions('maria@demo.local')).toContain('dependent.delete'); }); test('the export downloads a file holding the profile', async ({ page }) => { await page.goto('/es/perfil'); const download = page.waitForEvent('download'); await page.getByRole('link', { name: es['profile.myData.export'] }).click(); const file = await download; expect(file.suggestedFilename()).toMatch(/^impuestos-datos-\d{4}-\d{2}-\d{2}\.json$/); const stream = await file.createReadStream(); const chunks: Buffer[] = []; for await (const chunk of stream) chunks.push(chunk as Buffer); const data = JSON.parse(Buffer.concat(chunks).toString('utf8')) as { profile: { fullName: string } | null; account: { email: string }; }; expect(data.account.email).toBe('maria@demo.local'); expect(data.profile?.fullName).toBe('Maria Gonzalez'); expect(readAuditActions('maria@demo.local')).toContain('data.export'); }); test('deleting the account asks for the email before it will proceed', async ({ page }) => { await page.goto('/es/perfil'); await page.getByRole('button', { name: es['profile.myData.delete'] }).click(); const confirm = page.getByRole('button', { name: es['profile.myData.deleteCta'] }); await expect(confirm).toBeDisabled(); await page.getByLabel(es['profile.myData.deletePrompt'].replace('{email}', 'maria@demo.local')).fill('nope@demo.local'); await expect(confirm).toBeDisabled(); // Stops short of confirming: this account is the showcase data for every other test. await page.getByRole('button', { name: es['common.cancel'] }).click(); }); }); /** The toggle knob used to render outside its track, which read as a broken control. */ test.describe('switch', () => { test('keeps its knob inside the track in both states', async ({ page }) => { await page.goto('/es/login'); await page.getByLabel(es['auth.register.email']).fill('maria@demo.local'); await page.getByLabel(es['auth.login.password']).fill('demo-maria-1'); await page.getByRole('button', { name: es['auth.login.submit'] }).click(); await expect(page).toHaveURL(/\/es\/inicio$/); await page.goto('/es/perfil'); const toggle = page.getByRole('switch', { name: es['setup.oblig.iva.title'] }); await expect(toggle).toBeVisible(); for (const _ of [0, 1]) { const track = await toggle.boundingBox(); const knob = await toggle.locator('span').boundingBox(); expect(track).not.toBeNull(); expect(knob).not.toBeNull(); expect(knob?.x ?? 0).toBeGreaterThanOrEqual(track?.x ?? 0); expect((knob?.x ?? 0) + (knob?.width ?? 0)).toBeLessThanOrEqual( (track?.x ?? 0) + (track?.width ?? 0), ); await toggle.click(); await page.waitForTimeout(250); } }); });