feat(jobs): integrate table and board workspace
This commit is contained in:
@@ -78,13 +78,39 @@ test("[PRES-J07 J05 W01 W02 E07 E08 E09] Board query membership matches Table an
|
||||
await page.goto("/kanban?q=Board&status=Saved");
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(24);
|
||||
await capture(page, info, "board-filtered-query-light-en");
|
||||
await page.getByRole('link', { name: 'Job Applications', exact: true }).click();
|
||||
await expect(page).toHaveURL(url => url.pathname === '/jobs' && url.search === '?q=Board&status=Saved');
|
||||
await page.getByRole('link', { name: 'Table', exact: true }).click();
|
||||
await expect(page).toHaveURL(url => url.pathname === '/jobs' && url.search === '?q=Board&status=Saved&view=table');
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(15);
|
||||
const visibleIds = await page.locator('[data-job-row-id]').evaluateAll(rows => rows.map(row => Number(row.getAttribute('data-job-row-id'))));
|
||||
expect(visibleIds.every(id => ids.slice(3).includes(id))).toBe(true);
|
||||
await page.goBack();
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(24);
|
||||
await page.goForward();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(15);
|
||||
await page.getByRole('button', { name: 'Go to next page' }).click();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(9);
|
||||
const secondPageIds = await page.locator('[data-job-row-id]').evaluateAll(rows => rows.map(row => row.getAttribute('data-job-row-id')));
|
||||
const viewReads: string[] = [];
|
||||
const recordRead = (request: import('@playwright/test').Request) => {
|
||||
if (request.method() === 'GET' && /^\/api\/jobapplications(?:\/board)?$/.test(new URL(request.url()).pathname)) viewReads.push(new URL(request.url()).pathname);
|
||||
};
|
||||
page.on('request', recordRead);
|
||||
const boardSwitch = page.getByRole('link', { name: 'Board', exact: true });
|
||||
await boardSwitch.focus(); await page.keyboard.press('Enter');
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(24);
|
||||
await expect(boardSwitch).toBeFocused();
|
||||
await expect(boardSwitch).toHaveAttribute('aria-current', 'page');
|
||||
expect(viewReads).toEqual(['/api/jobapplications/board']);
|
||||
expect((await page.locator('[data-kanban-card-id]').evaluateAll(cards => cards.map(card => Number(card.getAttribute('data-kanban-card-id')))))).toEqual(expect.arrayContaining(ids.slice(3)));
|
||||
await capture(page, info, 'integrated-filtered-board-keyboard');
|
||||
await page.getByRole('link', { name: 'Table', exact: true }).click();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(9);
|
||||
expect(await page.locator('[data-job-row-id]').evaluateAll(rows => rows.map(row => row.getAttribute('data-job-row-id')))).toEqual(secondPageIds);
|
||||
expect(viewReads).toEqual(['/api/jobapplications/board', '/api/jobapplications']);
|
||||
page.off('request', recordRead);
|
||||
await capture(page, info, 'integrated-filtered-table-page-two');
|
||||
await page.goBack();
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(24);
|
||||
const filteredControl = page.locator(`[data-kanban-card-id="${ids[4]}"] [role="button"]`);
|
||||
await filteredControl.focus(); await page.keyboard.press('Space');
|
||||
await page.getByRole('group', { name: 'Active column' }).focus(); await page.keyboard.press('Enter');
|
||||
@@ -96,11 +122,24 @@ test("[PRES-J07 J05 W01 W02 E07 E08 E09] Board query membership matches Table an
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(0);
|
||||
await expect(page.getByText('No jobs in this group yet.')).toHaveCount(3);
|
||||
await capture(page, info, 'board-zero-query-light-en');
|
||||
await page.getByRole('link', { name: 'Table', exact: true }).click();
|
||||
await expect(page.getByText('No jobs found.')).toBeVisible();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(0);
|
||||
await page.getByRole('link', { name: 'Board', exact: true }).click();
|
||||
await expect(page.getByText('No jobs in this group yet.')).toHaveCount(3);
|
||||
|
||||
await page.goto('/jobs?q=Board&status=Take-home%20assignment&view=table');
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(1);
|
||||
await expect(page.locator(`[data-job-row-id="${ids[2]}"]`)).toBeVisible();
|
||||
await page.getByRole('link', { name: 'Board', exact: true }).click();
|
||||
await expect(page.locator('[data-kanban-card-id]')).toHaveCount(1);
|
||||
await expect(page.locator(`[data-kanban-card-id="${ids[2]}"]`)).toBeVisible();
|
||||
await capture(page, info, 'integrated-custom-status-board');
|
||||
|
||||
await page.goto("/kanban?source=board");
|
||||
const cards = page.locator("[data-kanban-card-id]");
|
||||
await expect(cards).toHaveCount(27);
|
||||
expect(new URL(page.url()).search).toBe("?source=board");
|
||||
expect(new URL(page.url()).search).toBe("?source=board&view=board");
|
||||
expect((await page.request.get(`${apiUrl}/jobapplications/board`)).status()).toBe(200);
|
||||
const tablePage = await (await page.request.get(`${apiUrl}/jobapplications?page=1&pageSize=15&q=Board`)).json();
|
||||
expect(tablePage.items.length).toBe(15);
|
||||
@@ -115,11 +154,21 @@ test("[PRES-J07 J05 W01 W02 E07 E08 E09] Board query membership matches Table an
|
||||
await expect(cards).toHaveCount(27);
|
||||
await expect(page.getByRole("group", { name: t.kanbanColumnLabel.replace("{label}", t.pipelineGroupNotApplied) })).toBeVisible();
|
||||
await expect(page.getByRole("group", { name: t.kanbanColumnNotDropTarget.replace("{label}", t.kanbanGroupOther) })).toBeVisible();
|
||||
await expect(page.getByRole("link", { name: t.jobApplications })).toHaveAttribute("href", "/jobs?source=board");
|
||||
await expect(page.getByRole("link", { name: t.jobsTableView, exact: true })).toHaveAttribute("href", "/jobs?source=board&view=table");
|
||||
await capture(page, info, `board-desktop-${mode}-${language}`);
|
||||
await page.getByRole("link", { name: t.jobsTableView, exact: true }).click();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(15);
|
||||
await capture(page, info, `integrated-table-desktop-${mode}-${language}`);
|
||||
await page.getByRole("link", { name: t.jobsBoardView, exact: true }).click();
|
||||
await expect(cards).toHaveCount(27);
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await expect(page.getByRole("group", { name: t.kanbanColumnLabel.replace("{label}", t.pipelineGroupNotApplied) })).toBeVisible();
|
||||
await capture(page, info, `board-phone-${mode}-${language}`);
|
||||
await page.getByRole("link", { name: t.jobsTableView, exact: true }).click();
|
||||
await expect(page.locator('[data-job-row-id]')).toHaveCount(15);
|
||||
await capture(page, info, `integrated-table-phone-${mode}-${language}`);
|
||||
await page.getByRole("link", { name: t.jobsBoardView, exact: true }).click();
|
||||
await expect(cards).toHaveCount(27);
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth + 1)).toBe(true);
|
||||
if (language === "en") await scan(page, info, `board-phone-${mode}`);
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
@@ -197,13 +246,30 @@ test("[PRES-J07 J05 W01 W02 E07 E08 E09] Board query membership matches Table an
|
||||
await expect(page).toHaveURL(new RegExp(`/jobs/${ids[0]}$`));
|
||||
await expect(page.getByRole("heading", { name: /Seniorrådgiver/ })).toBeVisible();
|
||||
await page.goBack();
|
||||
await expect(page).toHaveURL(url => url.pathname === "/kanban" && url.search === "?source=board");
|
||||
await expect(page).toHaveURL(url => url.pathname === "/jobs" && url.search === "?source=board&view=board");
|
||||
await expect(savedControl).toBeFocused();
|
||||
} finally {
|
||||
await admin.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
test("[PRES-J05 J07 E07 W01] legacy Board replaces history and preserves query, hash and route state; default Jobs stays Table", async ({ page }) => {
|
||||
await login(page.request, "e2e@example.test");
|
||||
await page.goto('/jobs?view=unknown&q=absent');
|
||||
await expect(page.getByRole('link', { name: 'Table', exact: true })).toHaveAttribute('aria-current', 'page');
|
||||
await expect(page.getByText('No jobs found.')).toBeVisible();
|
||||
await page.evaluate(() => history.pushState({ ...history.state, usr: { integrationSentinel: 'preserved' } }, '', '/kanban?q=absent&status=Custom+review&page=2&view=table#retained'));
|
||||
const length = await page.evaluate(() => history.length);
|
||||
await page.reload();
|
||||
await expect(page).toHaveURL(url => url.pathname === '/jobs' && url.searchParams.get('view') === 'board' && url.searchParams.get('status') === 'Custom review' && url.searchParams.get('q') === 'absent' && url.searchParams.get('page') === '2' && url.hash === '#retained');
|
||||
await expect(page.getByRole('link', { name: 'Board', exact: true })).toHaveAttribute('aria-current', 'page');
|
||||
expect(await page.evaluate(() => history.length)).toBe(length);
|
||||
expect(await page.evaluate(() => history.state.usr.integrationSentinel)).toBe('preserved');
|
||||
await page.goBack();
|
||||
await expect(page).toHaveURL(/\/jobs\?view=unknown&q=absent$/);
|
||||
await expect(page.getByRole('link', { name: 'Table', exact: true })).toHaveAttribute('aria-current', 'page');
|
||||
});
|
||||
|
||||
test("[PRES-J07 E08] Board loading, retryable error and fully empty columns", async ({ page }, info) => {
|
||||
test.setTimeout(90_000);
|
||||
await page.goto("/login");
|
||||
@@ -219,6 +285,8 @@ test("[PRES-J07 E08] Board loading, retryable error and fully empty columns", as
|
||||
else await route.fulfill({ json: [] });
|
||||
});
|
||||
await page.goto("/kanban", { waitUntil: "domcontentloaded" });
|
||||
// The shared workspace also has a lazy-renderer loading state. Wait for the actual read.
|
||||
await expect.poll(() => typeof release).toBe("function");
|
||||
await expect(page.getByRole("progressbar")).toBeVisible();
|
||||
await capture(page, info, "board-loading-light-en");
|
||||
state = "error"; release();
|
||||
|
||||
Reference in New Issue
Block a user