diff --git a/e2e/tests/add-task-bar/add-task-bar-date-picker.spec.ts b/e2e/tests/add-task-bar/add-task-bar-date-picker.spec.ts index 867253538..da3be01e5 100644 --- a/e2e/tests/add-task-bar/add-task-bar-date-picker.spec.ts +++ b/e2e/tests/add-task-bar/add-task-bar-date-picker.spec.ts @@ -1,5 +1,6 @@ import { type Locator, type Page } from '@playwright/test'; import { expect, test } from '../../fixtures/test.fixture'; +import { ensureGlobalAddTaskBarOpen } from '../../utils/element-helpers'; const ADD_TASK_BAR = 'add-task-bar.global'; const ADD_TASK_INPUT = `${ADD_TASK_BAR} input`; @@ -8,20 +9,6 @@ const CLEAR_DUE_BUTTON = `${ADD_TASK_BAR} [data-test="add-task-bar-clear-due-btn const SCHEDULE_DIALOG = 'dialog-schedule-task'; const QUICK_ACCESS_BTN = '.quick-access button'; -const ensureGlobalAddTaskBarOpen = async (page: Page): Promise => { - const addTaskInput = page.locator(ADD_TASK_INPUT).first(); - const isVisible = await addTaskInput.isVisible().catch(() => false); - - if (!isVisible) { - const addBtn = page.locator('.tour-addBtn').first(); - await addBtn.waitFor({ state: 'visible', timeout: 10000 }); - await addBtn.click(); - } - - await addTaskInput.waitFor({ state: 'visible', timeout: 10000 }); - return addTaskInput; -}; - const openScheduleDialogFromBar = async ( page: Page, ): Promise<{ dialog: Locator; dueButton: Locator }> => { diff --git a/e2e/tests/search/global-search.spec.ts b/e2e/tests/search/global-search.spec.ts index 22eaf282f..280ad2621 100644 --- a/e2e/tests/search/global-search.spec.ts +++ b/e2e/tests/search/global-search.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from '../../fixtures/test.fixture'; +import { ensureGlobalAddTaskBarOpen } from '../../utils/element-helpers'; /** * Global Search E2E Tests @@ -77,22 +78,15 @@ test.describe('Global Search', () => { await workViewPage.addTask(taskName); await expect(page.locator('task').filter({ hasText: taskName })).toBeVisible(); - // Try to focus on add task input if visible - const addTaskInput = page.locator('add-task-bar.global input'); - const isInputVisible = await addTaskInput - .isVisible({ timeout: 3000 }) - .catch(() => false); + // Ensure the add task bar is open and get the input + const addTaskInput = await ensureGlobalAddTaskBarOpen(page); - if (isInputVisible) { - await addTaskInput.click(); + // Type part of the task name + await addTaskInput.fill(testPrefix); + await page.waitForTimeout(500); - // Type part of the task name - await addTaskInput.fill(testPrefix); - await page.waitForTimeout(500); - - // Clear the input - await addTaskInput.clear(); - } + // Clear the input + await addTaskInput.clear(); await page.keyboard.press('Escape'); diff --git a/e2e/utils/element-helpers.ts b/e2e/utils/element-helpers.ts index 301c44e09..4054eef91 100644 --- a/e2e/utils/element-helpers.ts +++ b/e2e/utils/element-helpers.ts @@ -1,4 +1,4 @@ -import type { Locator } from '@playwright/test'; +import type { Locator, Page } from '@playwright/test'; /** * Safely checks if an element is visible, returning false on any error. @@ -33,3 +33,26 @@ export const safeIsEnabled = async (locator: Locator): Promise => { return false; } }; + +/** + * Ensures the global add task bar is open and returns the input locator. + * If the bar is closed, it will click the add button to open it. + * Uses proper condition-based waiting to avoid race conditions. + * + * @param page - Playwright page object + * @returns Promise - The add task input locator, ready for interaction + */ +export const ensureGlobalAddTaskBarOpen = async (page: Page): Promise => { + const ADD_TASK_INPUT = 'add-task-bar.global input'; + const addTaskInput = page.locator(ADD_TASK_INPUT).first(); + const isVisible = await addTaskInput.isVisible().catch(() => false); + + if (!isVisible) { + const addBtn = page.locator('.tour-addBtn').first(); + await addBtn.waitFor({ state: 'visible', timeout: 10000 }); + await addBtn.click(); + } + + await addTaskInput.waitFor({ state: 'visible', timeout: 10000 }); + return addTaskInput; +};