dev1/tests/e2e/23-educational-programs-select-school.spec.mjs

112 lines
4.8 KiB
JavaScript

// @ts-check
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
test.describe('@p0 Educational Programs — Select School → premium guard', () => {
test.setTimeout(20000);
test('plan education → programs page → Select School → confirm → redirected to /paywall (non-premium)', async ({ page }) => {
const user = loadTestUser();
// ------- helpers -------
async function signIn() {
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 });
}
async function ensureSuggestions() {
await page.goto('/career-explorer', { waitUntil: 'networkidle' });
const tile = page.locator('div.grid button').first();
if (await tile.isVisible({ timeout: 1500 }).catch(() => false)) return;
const reloadBtn = page.getByRole('button', { name: /Reload Career Suggestions/i });
await expect(reloadBtn).toBeVisible();
await reloadBtn.click();
const overlay = page.getByText(/Loading Career Suggestions/i).first();
await overlay.isVisible({ timeout: 2000 }).catch(() => {});
await expect
.poll(async () => {
return await page.evaluate(() => {
try {
const s = localStorage.getItem('careerSuggestionsCache');
const arr = s ? JSON.parse(s) : [];
return Array.isArray(arr) ? arr.length : 0;
} catch { return 0; }
});
}, { timeout: 60000, message: 'careerSuggestionsCache not populated' })
.toBeGreaterThan(0);
await expect(tile).toBeVisible({ timeout: 10000 });
}
async function addOneToComparison() {
const firstTile = page.locator('div.grid button').first();
await expect(firstTile).toBeVisible({ timeout: 8000 });
await firstTile.click();
await expect(page.getByRole('button', { name: /Add to Comparison/i }))
.toBeVisible({ timeout: 15000 });
await page.getByRole('button', { name: /Add to Comparison/i }).click();
// Ratings modal → Save (neutral)
const overlay = page.locator('div.fixed.inset-0');
if (await overlay.isVisible({ timeout: 2000 }).catch(() => false)) {
const dlg = overlay.locator('div[role="dialog"], div.bg-white').first();
const selects = dlg.locator('select');
const sc = await selects.count().catch(() => 0);
for (let i = 0; i < sc; i++) {
const sel = selects.nth(i);
const has3 = await sel.locator('option[value="3"]').count().catch(() => 0);
if (has3) await sel.selectOption('3');
}
const tb = dlg.locator('input, textarea, [role="textbox"]').first();
if (await tb.isVisible().catch(() => false)) await tb.fill('3');
const saveBtn = dlg.getByRole('button', { name: /^(Save|Save Ratings|Confirm|Done)$/i });
if (await saveBtn.isVisible({ timeout: 800 }).catch(() => false)) await saveBtn.click();
await overlay.waitFor({ state: 'hidden', timeout: 5000 }).catch(() => {});
}
}
// ------- flow -------
await signIn();
await ensureSuggestions();
await addOneToComparison();
// Open the row → Plan your Education/Skills
const table = page.locator('table');
await table.waitFor({ state: 'attached', timeout: 8000 }).catch(() => {});
const row = table.locator('tbody tr').first();
await expect(row).toBeVisible({ timeout: 8000 });
page.once('dialog', d => d.accept());
await row.getByRole('button', { name: /Plan your Education\/Skills/i }).click();
// Land on Educational Programs; wait for school cards to render
await expect(page).toHaveURL(/\/educational-programs(\?|$)/, { timeout: 20000 });
const programText = page.getByText(/^Program:\s*/i).first();
const selectBtn = page.getByRole('button', { name: /^Select School$/i }).first();
await expect(programText).toBeVisible({ timeout: 30000 });
await expect(selectBtn).toBeVisible({ timeout: 30000 });
// Draft calls must not block navigation: stub premium draft API to succeed
await page.route('**/api/premium/onboarding/draft', async (route) => {
// return minimal OK payload regardless of method
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ data: {} }),
});
});
// Click Select School → confirm → PremiumRoute guard should redirect to /paywall (non-premium)
page.once('dialog', d => d.accept());
await selectBtn.click();
await expect(page).toHaveURL(/\/paywall(\?|$)/, { timeout: 20000 });
});
});