149 lines
5.8 KiB
JavaScript
149 lines
5.8 KiB
JavaScript
|
|
// @ts-nocheck
|
|
import { test, expect } from '@playwright/test';
|
|
import { loadTestUser } from '../utils/testUser.js';
|
|
|
|
const ENFORCE = process.env.APTIVA_ENFORCE_BUDGETS === '1';
|
|
|
|
// Budgets (ms) — adjust here when needed
|
|
const B = {
|
|
signup_areas: 15000, // state change -> areas select enabled & options>1 (dev may be slow)
|
|
reload_cold: 60000, // click Reload -> careerSuggestionsCache length > 0
|
|
modal_cold: 3000, // click tile -> Add to Comparison visible
|
|
};
|
|
|
|
function log(name, ms, budget) {
|
|
console.log(`${name}: ${Math.round(ms)} ms${budget ? ` (budget ≤ ${budget})` : ''}`);
|
|
if (ENFORCE && budget) expect(ms).toBeLessThanOrEqual(budget);
|
|
}
|
|
|
|
test.describe('@perf Focused Budgets', () => {
|
|
test.setTimeout(30000);
|
|
|
|
test('SignUp: Areas population time', async ({ page }) => {
|
|
await page.context().clearCookies();
|
|
await page.goto('/signup', { waitUntil: 'networkidle' });
|
|
|
|
// Select State (dropdown with "Select State" placeholder)
|
|
const stateSelect = page.locator('select').filter({
|
|
has: page.locator('option', { hasText: 'Select State' }),
|
|
});
|
|
await expect(stateSelect).toBeVisible();
|
|
|
|
const areaSelect = page.locator('select#area');
|
|
await expect(areaSelect).toBeVisible();
|
|
|
|
const STATE = 'GA'; // Georgia (populates areas)
|
|
const stateParam = encodeURIComponent(STATE);
|
|
|
|
const t0 = Date.now();
|
|
await stateSelect.selectOption(STATE);
|
|
|
|
// Wait for the API call and the UI to be interactable
|
|
await page.waitForResponse(
|
|
r => r.url().includes(`/api/areas?state=${stateParam}`) && r.request().method() === 'GET',
|
|
{ timeout: 20000 }
|
|
);
|
|
await expect(areaSelect).toBeEnabled({ timeout: 10000 });
|
|
await expect(async () => {
|
|
const count = await areaSelect.locator('option').count();
|
|
expect(count).toBeGreaterThan(1);
|
|
}).toPass({ timeout: 10000 });
|
|
|
|
log('signup_areas', Date.now() - t0, B.signup_areas);
|
|
});
|
|
|
|
test('Career Explorer: Reload Career Suggestions (cold)', async ({ page }) => {
|
|
const u = loadTestUser();
|
|
|
|
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 });
|
|
|
|
await page.goto('/career-explorer', { waitUntil: 'networkidle' });
|
|
|
|
// Force cold by clearing cache
|
|
await page.evaluate(() => localStorage.removeItem('careerSuggestionsCache'));
|
|
|
|
const reloadBtn = page.getByRole('button', { name: /Reload Career Suggestions/i });
|
|
await expect(reloadBtn).toBeVisible();
|
|
|
|
const t0 = Date.now();
|
|
await reloadBtn.click();
|
|
|
|
// Wait for overlay to appear (if it does), then for it to effectively finish and hide.
|
|
const overlayText = page.getByText(/Loading Career Suggestions/i).first();
|
|
const appeared = await overlayText.isVisible({ timeout: 2000 }).catch(() => false);
|
|
if (appeared) {
|
|
// Treat overlay hidden as 100%; otherwise poll the % and accept ≥95 as done.
|
|
await expect
|
|
.poll(async () => {
|
|
const stillVisible = await overlayText.isVisible().catch(() => false);
|
|
if (!stillVisible) return 100;
|
|
const t = (await overlayText.textContent()) || '';
|
|
const m = t.match(/(\d+)%/);
|
|
return m ? parseInt(m[1], 10) : 0;
|
|
}, { timeout: B.reload_cold, message: 'reload overlay did not complete' })
|
|
.toBeGreaterThanOrEqual(95);
|
|
await overlayText.waitFor({ state: 'hidden', timeout: B.reload_cold }).catch(() => {});
|
|
}
|
|
|
|
// Source of truth: cache populated after overlay completes
|
|
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: B.reload_cold, message: 'careerSuggestionsCache not populated' })
|
|
.toBeGreaterThan(0);
|
|
|
|
log('explorer_reload_cold', Date.now() - t0, B.reload_cold);
|
|
});
|
|
|
|
|
|
test('Career Explorer: CareerModal open (cold)', async ({ page }) => {
|
|
const u = loadTestUser();
|
|
|
|
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 });
|
|
|
|
await page.goto('/career-explorer', { waitUntil: 'networkidle' });
|
|
|
|
// Ensure at least one tile exists; if not, perform a quick reload
|
|
const tile = page.locator('div.grid button').first();
|
|
if (!(await tile.isVisible({ timeout: 1500 }).catch(() => false))) {
|
|
const reloadBtn = page.getByRole('button', { name: /Reload Career Suggestions/i });
|
|
await reloadBtn.click();
|
|
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 })
|
|
.toBeGreaterThan(0);
|
|
await expect(tile).toBeVisible({ timeout: 8000 });
|
|
}
|
|
|
|
const t0 = Date.now();
|
|
await tile.click();
|
|
await page.getByRole('button', { name: /Add to Comparison/i }).waitFor({ timeout: 15000 });
|
|
|
|
log('careermodal_open_cold', Date.now() - t0, B.modal_cold);
|
|
});
|
|
});
|