dev1/tests/e2e/45b-financial-profile.spec.mjs

83 lines
3.1 KiB
JavaScript

// tests/e2e/45b-financial-profile.spec.mjs
// @ts-check
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
const byName = (page, n) => page.locator(`input[name="${n}"]`).first();
// Label → first following input (works even without for/id)
const inputAfterLabel = (page, labelRe) =>
page.locator('label').filter({ hasText: labelRe }).first()
.locator('xpath=following::input[1]').first();
test.describe('@p1 Profile — Financial editor (45b)', () => {
test.setTimeout(45000);
test('Save financial profile (accept alert) → leaves page', async ({ page }) => {
const u = loadTestUser();
// Premium gate
await page.route(
/\/api\/user-profile\?fields=.*(firstname|is_premium|is_pro_premium).*/i,
r => r.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ firstname: 'Tester', is_premium: 1, is_pro_premium: 0 })
})
);
// Deterministic GET/POST for the form
await page.route('**/api/premium/financial-profile', async route => {
if (route.request().method() === 'GET') {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
current_salary: 0,
additional_income: 0,
monthly_expenses: 0,
monthly_debt_payments: 0,
retirement_savings: 0,
emergency_fund: 0,
retirement_contribution: 0,
emergency_contribution: 0,
extra_cash_emergency_pct: 50,
extra_cash_retirement_pct: 50
})
});
} else if (route.request().method() === 'POST') {
await route.fulfill({ status: 200, body: '{}' });
} else {
await route.fallback();
}
});
// Sign in
await page.context().clearCookies();
await page.goto('/signin', { waitUntil: 'domcontentloaded' });
await page.getByPlaceholder('Username', { exact: true }).fill(u.username);
await page.getByPlaceholder('Password', { exact: true }).fill(u.password);
await page.getByRole('button', { name: /^Sign In$/ }).click();
await page.waitForURL('**/signin-landing**', { timeout: 15_000 });
// Go to form
await page.goto('/financial-profile', { waitUntil: 'domcontentloaded' });
await expect(page.getByRole('heading', { name: /Edit\s*Your\s*Financial\s*Profile/i }))
.toBeVisible({ timeout: 15_000 });
// Fill minimal fields
await byName(page, 'currentSalary').fill('55000');
// This field has NO name attribute → select by label then first input
await inputAfterLabel(page, /Monthly\s*Living\s*Expenses/i).fill('1800');
await byName(page, 'monthlyDebtPayments').fill('200');
await byName(page, 'extraCashEmergencyPct').fill('40'); // complements to 60
// Accept expected alert then leave page
page.once('dialog', d => d.accept().catch(() => {}));
await page.getByRole('button', { name: /^Save$/ }).click();
await expect(page).not.toHaveURL(/\/financial-profile$/i, { timeout: 20_000 });
});
});