test(e2e): tighten boards #7498 regression specs

Multi-review feedback: drop waitForTimeout (project rule), use the
taskPage.markTaskAsDone helper instead of raw locator clicks, and scope
the Eisenhower assertion to the specific quadrant the task belongs in.
Also exact-match the Kanban "Create Tag" button to avoid matching the
Eisenhower tab's plural label when both tab bodies briefly co-exist.
This commit is contained in:
Johannes Millan 2026-05-06 15:52:27 +02:00
parent a66893abc6
commit 8dd7cd99ef
2 changed files with 31 additions and 28 deletions

View file

@ -10,6 +10,7 @@ test.describe('Boards #7498 — Kanban', () => {
test('task with In Progress tag lands in DONE after done-toggle', async ({
page,
workViewPage,
taskPage,
testPrefix,
}) => {
await workViewPage.waitForTaskList();
@ -28,10 +29,12 @@ test.describe('Boards #7498 — Kanban', () => {
// On a fresh profile the Kanban panels reference KANBAN_IN_PROGRESS which
// doesn't exist yet — the board renders a "Create Tag" prompt instead of
// the columns. Click it and wait for the panels to appear.
const createTagsBtn = page.locator('button', { hasText: /create tags?/i });
await createTagsBtn.waitFor({ state: 'visible', timeout: 10000 });
await createTagsBtn.click();
// the columns. Match the singular Kanban label exactly so we don't also
// pick up the Eisenhower tab's "Create Tags" button when both tab bodies
// are momentarily in the DOM during the mat-tab transition.
const createTagBtn = page.getByRole('button', { name: 'Create Tag', exact: true });
await createTagBtn.waitFor({ state: 'visible', timeout: 10000 });
await createTagBtn.click();
const inProgressPanel = page
.locator('board-panel')
@ -48,7 +51,6 @@ test.describe('Boards #7498 — Kanban', () => {
await inlineInput.waitFor({ state: 'visible', timeout: 5000 });
await inlineInput.fill(taskName);
await page.keyboard.press('Enter');
await page.keyboard.press('Escape');
const inProgressTask = inProgressPanel
.locator('planner-task')
@ -56,19 +58,17 @@ test.describe('Boards #7498 — Kanban', () => {
.first();
await expect(inProgressTask).toBeVisible({ timeout: 10000 });
// Click the done-toggle (circle) on the task.
await inProgressTask.hover();
await inProgressTask.locator('done-toggle').click();
await page.waitForTimeout(500);
await taskPage.markTaskAsDone(inProgressTask);
// The task should land in the DONE column. Pre-fix it would have been
// filtered out by `excludedTagIds: [IN_PROGRESS_TAG.id]`.
// filtered out by `excludedTagIds: [IN_PROGRESS_TAG.id]`. Playwright auto-
// retries until the state settles after the toggle animation.
const donePanel = page
.locator('board-panel')
.filter({ has: page.locator('header .title', { hasText: /^done$/i }) })
.first();
await expect(
donePanel.locator('planner-task').filter({ hasText: taskName }).first(),
).toBeVisible({ timeout: 5000 });
).toBeVisible();
});
});

View file

@ -8,15 +8,18 @@ import { expect, test } from '../../fixtures/test.fixture';
* original quadrant.
*/
test.describe('Boards #7498', () => {
test('Eisenhower: task stays visible after done-toggle', async ({
test('Eisenhower: task stays in its quadrant after done-toggle', async ({
page,
workViewPage,
taskPage,
testPrefix,
}) => {
await workViewPage.waitForTaskList();
// Plain task with no tags lands in the NOT_URGENT_AND_NOT_IMPORTANT
// quadrant (excluded: [Important, Urgent], included: []).
await workViewPage.addTask('repro7498 task');
const taskName = `${testPrefix}repro7498-eisenhower`;
await workViewPage.addTask(taskName);
await page.goto('/#/boards');
await page.waitForLoadState('networkidle');
@ -35,24 +38,24 @@ test.describe('Boards #7498', () => {
await createTagsBtn.click();
}
const task = page
.locator('board-panel planner-task')
.filter({ hasText: 'repro7498 task' })
const notUrgentNotImportantPanel = page
.locator('board-panel')
.filter({
has: page.locator('header .title', { hasText: /not urgent.*not important/i }),
})
.first();
await expect(task).toBeVisible({ timeout: 10000 });
await expect(notUrgentNotImportantPanel).toBeVisible({ timeout: 10000 });
await task.hover();
await task.locator('done-toggle').click();
const task = notUrgentNotImportantPanel
.locator('planner-task')
.filter({ hasText: taskName })
.first();
await expect(task).toBeVisible();
// Wait past the 200ms done-animation delay used in toggleDoneWithAnimation.
await page.waitForTimeout(500);
await taskPage.markTaskAsDone(task);
// Fixed behavior: the task remains visible somewhere on the board.
await expect(
page
.locator('board-panel planner-task')
.filter({ hasText: 'repro7498 task' })
.first(),
).toBeVisible();
// Fixed behavior: the task is still in its original quadrant — Playwright
// auto-retries the assertion until the toggle's 200ms animation settles.
await expect(task).toBeVisible();
});
});