From 7a870149ba89a97a7467e72b9cf6ca6a453989b8 Mon Sep 17 00:00:00 2001 From: Lars de Ridder Date: Thu, 12 Mar 2026 15:57:24 +0100 Subject: [PATCH] test(task): add Playwright tests for bucket select in task detail --- frontend/tests/e2e/task/bucket-select.spec.ts | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 frontend/tests/e2e/task/bucket-select.spec.ts diff --git a/frontend/tests/e2e/task/bucket-select.spec.ts b/frontend/tests/e2e/task/bucket-select.spec.ts new file mode 100644 index 000000000..c72cf41cc --- /dev/null +++ b/frontend/tests/e2e/task/bucket-select.spec.ts @@ -0,0 +1,99 @@ +import {test, expect} from '../../support/fixtures' +import {BucketFactory} from '../../factories/bucket' +import {ProjectFactory} from '../../factories/project' +import {TaskFactory} from '../../factories/task' +import {ProjectViewFactory} from '../../factories/project_view' +import {TaskBucketFactory} from '../../factories/task_buckets' + +async function createKanbanTaskInBucket() { + const projects = await ProjectFactory.create(1) + const views = await ProjectViewFactory.create(1, { + id: 1, + project_id: projects[0].id, + view_kind: 3, + bucket_configuration_mode: 1, + }) + const buckets = await BucketFactory.create(2, { + project_view_id: views[0].id, + }) + const tasks = await TaskFactory.create(1, { + project_id: projects[0].id, + }) + await TaskBucketFactory.create(1, { + task_id: tasks[0].id, + bucket_id: buckets[0].id, + project_view_id: views[0].id, + }) + return { + project: projects[0], + view: views[0], + buckets, + task: tasks[0], + } +} + +test.describe('Task Bucket Select', () => { + test('Shows the current bucket name when opening a task from a kanban view', async ({authenticatedPage: page}) => { + const {project, view, buckets, task} = await createKanbanTaskInBucket() + + await page.goto(`/projects/${project.id}/${view.id}`) + await expect(page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title})).toBeVisible() + await page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title}).click() + await expect(page).toHaveURL(new RegExp(`/tasks/${task.id}`)) + + await expect(page.locator('.task-view .subtitle')).toContainText(buckets[0].title) + }) + + test('Can change the bucket from the task detail view', async ({authenticatedPage: page}) => { + const {project, view, buckets, task} = await createKanbanTaskInBucket() + + await page.goto(`/projects/${project.id}/${view.id}`) + await expect(page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title})).toBeVisible() + await page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title}).click() + await expect(page).toHaveURL(new RegExp(`/tasks/${task.id}`)) + + // Click the bucket name to open the dropdown + await page.locator('.task-view .subtitle .bucket-name').click() + // Select the other bucket + await page.locator('.task-view .subtitle .dropdown-item').filter({hasText: buckets[1].title}).click() + + await expect(page.locator('.global-notification')).toContainText('Success') + await expect(page.locator('.task-view .subtitle')).toContainText(buckets[1].title) + }) + + test('Does not show the bucket selector when project has no kanban view', async ({authenticatedPage: page}) => { + const projects = await ProjectFactory.create(1) + // Only create a list view, no kanban view + const views = await ProjectViewFactory.create(1, { + id: 1, + project_id: projects[0].id, + view_kind: 0, + }) + const tasks = await TaskFactory.create(1, { + project_id: projects[0].id, + }) + + await page.goto(`/projects/${projects[0].id}/${views[0].id}`) + await page.locator('.tasks .task').filter({hasText: tasks[0].title}).click() + await expect(page).toHaveURL(new RegExp(`/tasks/${tasks[0].id}`)) + + await expect(page.locator('.task-view .subtitle .bucket-name')).not.toBeVisible() + }) + + test('Keeps action buttons visible after changing the bucket', async ({authenticatedPage: page}) => { + const {project, view, buckets, task} = await createKanbanTaskInBucket() + + await page.goto(`/projects/${project.id}/${view.id}`) + await expect(page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title})).toBeVisible() + await page.locator('.kanban .bucket .tasks .task').filter({hasText: task.title}).click() + await expect(page).toHaveURL(new RegExp(`/tasks/${task.id}`)) + + // Change the bucket + await page.locator('.task-view .subtitle .bucket-name').click() + await page.locator('.task-view .subtitle .dropdown-item').filter({hasText: buckets[1].title}).click() + await expect(page.locator('.global-notification')).toContainText('Success') + + // Action buttons should still be visible + await expect(page.locator('.task-view .action-buttons .button').filter({hasText: 'Done'})).toBeVisible() + }) +})