dev1/tests/e2e/51-scenario-edit-modal.spec.mjs
2025-09-18 13:26:16 +00:00

156 lines
5.8 KiB
JavaScript

// @ts-nocheck
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
const j = (o) => JSON.stringify(o);
test.describe('@p1 ScenarioEditModal — save + retirement milestone (51)', () => {
test.setTimeout(20000);
test('Open modal, set retirement fields, save → creates Retirement milestone', async ({ page, request }) => {
const u = loadTestUser();
// ── Premium gate
await page.route(
/\/api\/user-profile\?fields=.*(firstname|is_premium|is_pro_premium|area|state).*/i,
r => r.fulfill({
status: 200,
contentType: 'application/json',
body: j({ firstname: 'Tester', is_premium: 1, is_pro_premium: 0, area: 'U.S.', state: 'GA' })
})
);
// ── Seed a scenario
const seed = await request.post('/api/premium/career-profile', {
data: { career_name: 'Software Developers', status: 'planned', start_date: '2025-01-01' }
});
const { career_profile_id } = await seed.json();
// ── CareerRoadmap deps (minimal)
await page.route(new RegExp(`/api/premium/career-profile/${career_profile_id}$`, 'i'), r =>
r.fulfill({
status: 200, contentType: 'application/json',
body: j({
id: career_profile_id,
scenario_title: 'SWE Plan',
career_name: 'Software Developers',
status: 'planned',
start_date: '2025-01-01',
college_enrollment_status: 'not_enrolled'
})
})
);
await page.route(/\/api\/premium\/financial-profile$/i, r => r.fulfill({
status: 200, contentType: 'application/json',
body: j({
current_salary: 90000,
additional_income: 0,
monthly_expenses: 2500,
monthly_debt_payments: 300,
retirement_savings: 10000,
emergency_fund: 3000,
retirement_contribution: 300,
emergency_contribution: 200,
extra_cash_emergency_pct: 50,
extra_cash_retirement_pct: 50
})
}));
await page.route(new RegExp(`/api/premium/college-profile\\?careerProfileId=${career_profile_id}$`, 'i'), r =>
r.fulfill({ status: 200, contentType: 'application/json', body: j({}) })
);
// Salary/Projections to keep UI calm
await page.route(/\/api\/salary\?*/i, r => r.fulfill({ status: 200, contentType: 'application/json', body: j({}) }));
await page.route(/\/api\/projections\/15-1252\?state=.*/i, r => r.fulfill({ status: 200, contentType: 'application/json', body: j({}) }));
// Milestones list for CareerRoadmap panel (empty)
await page.route(new RegExp(`/api/premium/milestones\\?careerProfileId=${career_profile_id}$`, 'i'), r =>
r.fulfill({ status: 200, contentType: 'application/json', body: j({ milestones: [] }) })
);
// POST /career-profile (upsert on save)
await page.route(/\/api\/premium\/career-profile$/i, async r => {
if (r.request().method() === 'POST') {
return r.fulfill({
status: 200, contentType: 'application/json',
body: j({ career_profile_id })
});
}
return r.fallback();
});
// GET milestones?careerProfileId=.. (check Retirement exists) → none
await page.route(/\/api\/premium\/milestones\?careerProfileId=\d+$/i, r => {
return r.fulfill({
status: 200, contentType: 'application/json',
body: j({ milestones: [] }) // no Retirement yet → should POST
});
});
// POST /milestone (create Retirement)
await page.route(/\/api\/premium\/milestone$/i, async r => {
if (r.request().method() === 'POST') {
return r.fulfill({ status: 200, contentType: 'application/json', body: j({ id: 70001 }) });
}
return r.fallback();
});
// PUT /milestones/:id (would be used if it already existed)
await page.route(/\/api\/premium\/milestones\/\d+$/i, async r => {
if (r.request().method() === 'PUT') {
return r.fulfill({ status: 200, body: '{}' });
}
return r.fallback();
});
// ── Navigate to roadmap
await page.goto(`/career-roadmap/${career_profile_id}`, { waitUntil: 'domcontentloaded' });
// Open the ScenarioEditModal
const editBtn = page.getByRole('button', { name: /^Edit Simulation Inputs$/i });
await expect(editBtn).toBeVisible({ timeout: 6000 });
await editBtn.click();
// Modal visible
const modalHeading = page.getByRole('heading', { name: /^Edit Scenario:/i }).first();
await expect(modalHeading).toBeVisible({ timeout: 6000 });
// Set retirement date and desired monthly income (robust selectors)
const retireField = page.locator('input[name="retirement_start_date"]').first();
const dtype = (await retireField.getAttribute('type')) || '';
if (dtype.toLowerCase() === 'date') {
await retireField.fill('2035-06-01');
} else {
await retireField.fill('');
await retireField.type('06/01/2035', { delay: 10 });
}
const incomeField = page.locator('input[name="desired_retirement_income_monthly"]').first();
await incomeField.fill('5500');
// Prepare network waits before clicking Save
const waitUpsert = page.waitForRequest(req =>
/\/api\/premium\/career-profile$/i.test(req.url()) && req.method() === 'POST'
);
const waitMilestonesCheck = page.waitForRequest(req =>
new RegExp(`/api/premium/milestones\\?careerProfileId=${career_profile_id}$`, 'i').test(req.url())
);
const waitRetirementCreateOrPut = page.waitForRequest(req =>
/\/api\/premium\/milestone($|\/\d+$)/i.test(req.url()) && /^(POST|PUT)$/.test(req.method())
);
// Save
await page.getByRole('button', { name: /^Save$/i }).click();
// Modal closes
await expect(modalHeading).toHaveCount(0, { timeout: 6000 });
// Verify requests fired
await Promise.all([
waitUpsert,
waitMilestonesCheck,
waitRetirementCreateOrPut
]);
});
});