dev1/tests/e2e/38-educational-programs-sorting.spec.mjs
2025-09-18 13:26:16 +00:00

89 lines
3.6 KiB
JavaScript

// @ts-nocheck
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
test.describe('@p1 Educational Programs — sorting (tuition vs distance)', () => {
test.setTimeout(120000);
test('sort toggles change ordering; list remains populated', async ({ page }) => {
const u = loadTestUser();
// Sign in
await page.context().clearCookies();
await page.goto('/signin', { waitUntil: 'networkidle' });
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: 15000 });
// Seed selectedCareer for programs fetch (UI does not render SOC/CIP)
await page.evaluate(() => {
localStorage.setItem('selectedCareer', JSON.stringify({
title: 'Data Analyst',
soc_code: '15-2051.00',
cip_code: ['11.0802', '04.0201']
}));
});
await page.goto('/educational-programs', { waitUntil: 'networkidle' });
// Wait for at least one card to render (match the card structure used in the component)
const card = page.locator('div.rounded.border.p-3.text-sm').first();
await expect(card).toBeVisible({ timeout: 30000 });
// Helper to read numbers from card list
async function readTuitionList() {
return await page.locator('div.rounded.border.p-3.text-sm').evaluateAll(nodes =>
nodes.map(n => {
const line = [...n.querySelectorAll('p')]
.map(p => p.textContent || '')
.find(t => /^In-State Tuition:\s*\$/.test(t));
if (!line) return NaN;
const match = line.replace(/,/g, '').match(/In-State Tuition:\s*\$(\d+(?:\.\d+)?)/i);
return match ? parseFloat(match[1]) : NaN;
}).filter(x => Number.isFinite(x))
);
}
async function readDistanceList() {
return await page.locator('div.rounded.border.p-3.text-sm').evaluateAll(nodes =>
nodes.map(n => {
const line = [...n.querySelectorAll('p')]
.map(p => p.textContent || '')
.find(t => /^Distance:\s*/i.test(t));
if (!line) return NaN;
const match = line.match(/Distance:\s*(\d+(?:\.\d+)?)\s*mi/i);
return match ? parseFloat(match[1]) : NaN; // NaN if "N/A"
}).filter(x => Number.isFinite(x))
);
}
const isNonDecreasing = (arr) => arr.every((v, i) => i === 0 || arr[i - 1] <= v);
// --- Default sort = Tuition ---
const tuitionBefore = await readTuitionList();
if (tuitionBefore.length >= 2) {
expect(isNonDecreasing(tuitionBefore)).toBeTruthy();
} else {
// At least the list is populated with cards
const cardCount = await page.locator('div.rounded.border.p-3.text-sm').count();
expect(cardCount).toBeGreaterThan(0);
}
// Switch Sort to Distance (the select is inside its label)
const sortSelect = page.locator('label:has-text("Sort")').locator('select');
await expect(sortSelect).toBeVisible();
await sortSelect.selectOption('distance');
// Wait for re-render by observing that either distances appear or first card block text changes
const distances = await readDistanceList();
if (distances.length >= 2) {
expect(isNonDecreasing(distances)).toBeTruthy();
} else {
// If distances are N/A (no ZIP), at least ensure the list remains populated
const cardCount = await page.locator('div.rounded.border.p-3.text-sm').count();
expect(cardCount).toBeGreaterThan(0);
}
});
});