156 lines
5.8 KiB
JavaScript
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
|
|
]);
|
|
});
|
|
});
|