62 lines
4.5 KiB
TypeScript
62 lines
4.5 KiB
TypeScript
import { test, expect, type APIRequestContext } from '../../../../../job-tracker-ui/node_modules/@playwright/test';
|
|
import { WIDGETS } from '../../../../../job-tracker-ui/src/dashboardLayout';
|
|
|
|
const api = 'http://localhost:5302/api';
|
|
const password = 'E2ePassword123!';
|
|
async function login(request: APIRequestContext, email: string) {
|
|
expect((await request.post(`${api}/auth/login`, { data: { email, password } })).status()).toBe(200);
|
|
const me = await (await request.get(`${api}/auth/me`)).json();
|
|
const csrf = (await request.storageState()).cookies.find(cookie => cookie.name === 'XSRF-TOKEN')!.value;
|
|
return { 'X-CSRF-TOKEN': csrf, 'X-Session-Context': me.sessionContext as string };
|
|
}
|
|
|
|
for (const size of ['standard', 'full'] as const) test(`All populated widgets at ${size} across responsive widths`, async ({ page, playwright }, info) => {
|
|
test.setTimeout(120000);
|
|
const admin = await playwright.request.newContext();
|
|
try {
|
|
const adminHeaders = await login(admin, 'e2e@example.test');
|
|
const email = `p8-sizes-${size}-${Date.now()}@example.test`;
|
|
expect((await admin.post(`${api}/users`, { headers: adminHeaders, data: { email, password, roles: [] } })).status()).toBe(200);
|
|
const headers = await login(page.request, email);
|
|
const created = await page.request.post(`${api}/companies`, { headers, data: { name: 'Very long Norwegian company name for readable widget layouts', source: 'Native size qualification' } });
|
|
expect(created.status()).toBe(201);
|
|
const companyId = (await created.json()).id;
|
|
expect((await page.request.post(`${api}/jobapplications`, { headers, data: { companyId, jobTitle: 'Senior platform developer', status: 'Applied', dateApplied: new Date(Date.now() - 86400000).toISOString(), responseReceived: true, responseDate: new Date().toISOString(), tags: 'TypeScript, Norsk programvareutvikling', salaryMin: 600000, salaryMax: 850000, salaryCurrency: 'NOK', salaryPeriod: 'year' } })).status()).toBe(201);
|
|
await page.route('**/*', route => ['localhost', '127.0.0.1'].includes(new URL(route.request().url()).hostname) ? route.continue() : route.abort());
|
|
await page.goto('/dashboard');
|
|
await page.getByRole('button', { name: 'Customize dashboard', exact: true }).click();
|
|
const editor = page.getByRole('region', { name: 'Editing dashboard', exact: true });
|
|
for (const widget of WIDGETS) if (widget.sizes.length > 1) {
|
|
const select = editor.locator(`[data-layout-row="${widget.id}"] select`);
|
|
await select.selectOption(size); await expect(select).toHaveValue(size);
|
|
}
|
|
await editor.getByRole('button', { name: 'Save layout', exact: true }).click();
|
|
await expect(editor).toHaveCount(0);
|
|
const readback = await (await page.request.get(`${api}/auth/preferences/dashboard`)).json();
|
|
expect(readback.widgets.every((widget: { id: string; size: string }) => widget.size === (widget.id === 'cards' ? 'full' : size))).toBe(true);
|
|
for (const summary of await page.locator('[data-dashboard-widget] details > summary').all()) await summary.click();
|
|
for (const width of [320, 768, 1024, 1440]) {
|
|
await page.setViewportSize({ width, height: 900 });
|
|
await expect(page.locator('[data-dashboard-widget]')).toHaveCount(9);
|
|
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1)).toBe(true);
|
|
const failures = await page.locator('[data-dashboard-widget]').evaluateAll(widgets => widgets.flatMap(widget => {
|
|
const box = widget.getBoundingClientRect();
|
|
return [...widget.querySelectorAll('table, svg, th, td')].filter(element => {
|
|
const rect = element.getBoundingClientRect();
|
|
return rect.width > 0 && (rect.right > box.right + 1 || rect.left < box.left - 1);
|
|
}).map(element => ({ widget: widget.getAttribute('data-dashboard-widget'), tag: element.tagName }));
|
|
}));
|
|
expect(failures).toEqual([]);
|
|
const amount = page.locator('[data-dashboard-widget="salary"]').getByText(new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'NOK', maximumFractionDigits: 0 }).format(725000), { exact: true });
|
|
await expect(amount).toBeVisible();
|
|
expect(await amount.evaluate(element => {
|
|
const range = document.createRange(); range.selectNodeContents(element);
|
|
return range.getClientRects().length;
|
|
})).toBe(1);
|
|
const screenshot = info.outputPath(`${size}-${width}.png`);
|
|
await page.screenshot({ path: screenshot, fullPage: true });
|
|
await info.attach(`${size}-${width}`, { path: screenshot, contentType: 'image/png' });
|
|
}
|
|
} finally { await admin.dispose(); }
|
|
});
|