dev1/tests/e2e/06-career-explorer.search.spec.mjs

112 lines
4.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
test.describe('@p1 Career Explorer — CareerSearch datalist', () => {
test.setTimeout(20000);
test('datalist commit opens modal; Change resets input', async ({ page }) => {
const user = loadTestUser();
// Helpers
async function closeAnyOverlay() {
const overlay = page.locator('div.fixed.inset-0');
if (!(await overlay.isVisible({ timeout: 500 }).catch(() => false))) return;
const dlg = overlay.locator('div[role="dialog"], div.bg-white').first();
// If modal asks for ratings, pick neutral values and Save/Continue so it goes away.
const selects = dlg.locator('select');
const sc = await selects.count().catch(() => 0);
for (let i = 0; i < sc; i++) {
const sel = selects.nth(i);
if (await sel.isVisible().catch(() => false)) {
const has3 = await sel.locator('option[value="3"]').count().catch(() => 0);
if (has3) await sel.selectOption('3');
else {
const opts = sel.locator('option');
const n = await opts.count().catch(() => 0);
for (let j = 0; j < n; j++) {
const v = await opts.nth(j).getAttribute('value');
if (v) { await sel.selectOption(v); break; }
}
}
}
}
const tb = dlg.locator('input, textarea, [role="textbox"]').first();
if (await tb.isVisible().catch(() => false)) await tb.fill('3');
const save = dlg.getByRole('button', { name: /(Save|Continue|Done|OK)/i });
const cancel = dlg.getByRole('button', { name: /(Cancel|Close)/i });
if (await save.isVisible({ timeout: 500 }).catch(() => false)) await save.click();
else if (await cancel.isVisible({ timeout: 500 }).catch(() => false)) await cancel.click();
else await page.keyboard.press('Escape');
await overlay.waitFor({ state: 'hidden', timeout: 5000 }).catch(() => {});
}
// Sign in
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 });
// Go to Career Explorer
await page.goto('/career-explorer', { waitUntil: 'networkidle' });
await expect(page.getByRole('heading', { name: /Explore Careers - use these tools/i })).toBeVisible();
await closeAnyOverlay();
const input = page.getByPlaceholder('Start typing a career...');
// If previously selected, the input is disabled; click Change to reset.
if (await input.isDisabled()) {
const changeLink = page.getByRole('button', { name: /^Change$/i }).or(page.getByText(/^Change$/));
await expect(changeLink).toBeVisible({ timeout: 5000 });
await changeLink.click();
await expect(input).toBeEnabled({ timeout: 2000 });
await expect(input).toHaveValue('');
}
// Type a partial and wait for datalist options to populate
await input.fill('block');
const options = page.locator('datalist#career-titles option');
await expect
.poll(async () => await options.count(), { timeout: 7000, message: 'no datalist options' })
.toBeGreaterThan(0);
// Take the first suggestion's exact value (e.g., "Blockchain Engineers")
const firstValue = await options.first().evaluate(el => el.value);
// Commit by setting exact value + blur (component commits on exact + blur)
await input.fill(firstValue);
await input.blur();
// Loading overlay may show; wait for it to appear (optional) then hide
const loading = page.getByText(/Loading Career/i).first(); // matches “Loading Career Suggestions…”
await loading.isVisible({ timeout: 2000 }).catch(() => {});
await loading.waitFor({ state: 'hidden', timeout: 60000 }).catch(() => {}); // guard slow cold path
// CareerModal should open (Add to Comparison button present)
await expect(page.getByRole('button', { name: /Add to Comparison/i })).toBeVisible({ timeout: 15000 });
// Close the modal (dont add in this test)
const closeBtn = page.getByRole('button', { name: /^Close$/i });
if (await closeBtn.isVisible().catch(() => false)) {
await closeBtn.click();
} else {
await page.keyboard.press('Escape');
}
// Input becomes disabled after selection; click Change to reset
await expect(input).toBeDisabled();
const changeLink = page.getByRole('button', { name: /^Change$/i }).or(page.getByText(/^Change$/));
await expect(changeLink).toBeVisible({ timeout: 5000 });
await changeLink.click();
// Now the input should be enabled and cleared
await expect(input).toBeEnabled();
await expect(input).toHaveValue('');
});
});