import { test, expect, Page } from '@playwright/test'; import { login, navigateAndWait, waitForElement, hoverAndWaitForVisible, createUniqueEntity, waitForNetworkIdle } from '../helpers/testHelpers'; // Helper to create a task async function createTask(page: Page, taskName: string) { const taskInput = page.locator('[data-testid="new-task-input"]'); await taskInput.fill(taskName); await taskInput.press('Enter'); await waitForNetworkIdle(page); } // Helper to open task edit modal async function openTaskEditModal(page: Page, taskName: string) { const taskContainer = page.locator('[data-testid*="task-item"]').filter({ hasText: taskName }); await expect(taskContainer).toBeVisible({ timeout: 15000 }); const editButton = taskContainer.locator('[data-testid*="task-edit"]'); await hoverAndWaitForVisible(taskContainer, editButton); await editButton.click(); const taskNameInput = page.locator('[data-testid="task-name-input"]'); await waitForElement(taskNameInput, { timeout: 15000 }); return taskNameInput; } // Helper to create a project async function createProject(page: Page, projectName: string) { // Find the "Add Project" button in the sidebar const addProjectButton = page.locator('button[aria-label="Add Project"]'); await expect(addProjectButton).toBeVisible(); // Click the Add Project button await addProjectButton.click(); // Wait for the Project Modal to appear await expect(page.locator('input[name="name"]')).toBeVisible({ timeout: 10000 }); // Fill in the project name const nameInput = page.locator('[data-testid="project-name-input"]'); await nameInput.click(); await nameInput.clear(); await nameInput.fill(projectName); // Verify the field has the expected value await expect(nameInput).toHaveValue(projectName, { timeout: 2000 }); // Wait for the save button to be enabled const saveButton = page.locator('[data-testid="project-save-button"]'); await expect(saveButton).toBeEnabled(); // Save the project await saveButton.click(); // Wait for modal to close await expect(page.locator('[data-testid="project-modal"]')).not.toBeVisible({ timeout: 15000 }); } // Helper to open project edit modal async function openProjectEditModal(page: Page, projectName: string) { // Click on the project in the projects list const projectCard = page.locator('[data-testid*="project-card"]').filter({ hasText: projectName }); await expect(projectCard).toBeVisible({ timeout: 15000 }); // Click the edit button const editButton = projectCard.locator('[data-testid*="project-edit"]'); await expect(editButton).toBeVisible(); await editButton.click(); // Wait for modal to open const nameInput = page.locator('[data-testid="project-name-input"]'); await waitForElement(nameInput, { timeout: 15000 }); return nameInput; } test('task created without priority selection defaults to None', async ({ page, baseURL }) => { const appUrl = await login(page, baseURL); await navigateAndWait(page, appUrl + '/tasks'); // Create a task without setting any priority const taskName = createUniqueEntity('Default Priority Task'); await createTask(page, taskName); // Open the task edit modal await openTaskEditModal(page, taskName); // Wait for modal to be in idle state await expect(page.locator('[data-testid="task-modal"][data-state="idle"]')).toBeVisible(); // Click the priority section icon to expand the priority section const prioritySectionButton = page.locator('button[title*="Priority"]').filter({ has: page.locator('svg') }); await prioritySectionButton.click(); // Wait for priority section to be expanded await expect(page.locator('[data-testid="priority-section"][data-state="expanded"]')).toBeVisible(); // Check that the priority dropdown shows "None" const priorityDropdown = page.locator('[data-testid="priority-dropdown"]'); await expect(priorityDropdown).toBeVisible(); // The dropdown should contain "None" text await expect(priorityDropdown).toContainText(/none/i); // Close modal without saving await page.keyboard.press('Escape'); await expect(page.locator('[data-testid="task-modal"]')).not.toBeVisible({ timeout: 5000 }); }); test('project created without priority selection defaults to None', async ({ page, baseURL }) => { const appUrl = await login(page, baseURL); await navigateAndWait(page, appUrl + '/projects'); // Click the "Add Project" button const addProjectButton = page.locator('button[aria-label="Add Project"]'); await expect(addProjectButton).toBeVisible(); await addProjectButton.click(); // Wait for the Project Modal to appear await expect(page.locator('[data-testid="project-modal"]')).toBeVisible({ timeout: 10000 }); // Fill in the project name const projectName = createUniqueEntity('Default Priority Project'); const nameInput = page.locator('[data-testid="project-name-input"]'); await nameInput.fill(projectName); // Click the priority section icon to expand the priority section const prioritySectionButton = page.locator('button[title*="Priority"]').filter({ has: page.locator('svg') }); await expect(prioritySectionButton).toBeVisible(); await prioritySectionButton.click(); // Wait for priority section to be expanded await page.waitForTimeout(300); // Check that the priority dropdown shows "None" const priorityDropdown = page.locator('[data-testid="priority-dropdown"]'); await expect(priorityDropdown).toBeVisible(); // The dropdown should contain "None" text await expect(priorityDropdown).toContainText(/none/i); // Close modal without saving await page.keyboard.press('Escape'); // Handle discard changes dialog (appears because we filled in the project name) const discardButton = page.locator('[data-testid="discard-dialog-confirm"]'); await expect(discardButton).toBeVisible({ timeout: 5000 }); await discardButton.click(); await expect(page.locator('[data-testid="project-modal"]')).not.toBeVisible({ timeout: 5000 }); }); test('task priority can be set to None after being set to High', async ({ page, baseURL }) => { const appUrl = await login(page, baseURL); await navigateAndWait(page, appUrl + '/tasks'); // Create a task const taskName = createUniqueEntity('Priority Clear Task'); await createTask(page, taskName); // Open the task edit modal await openTaskEditModal(page, taskName); // Wait for modal to be in idle state await expect(page.locator('[data-testid="task-modal"][data-state="idle"]')).toBeVisible(); // Expand priority section const prioritySectionButton = page.locator('button[title*="Priority"]').filter({ has: page.locator('svg') }); await prioritySectionButton.click(); await expect(page.locator('[data-testid="priority-section"][data-state="expanded"]')).toBeVisible(); // Set priority to High const priorityDropdown = page.locator('[data-testid="priority-dropdown"]'); await priorityDropdown.click(); await expect(page.locator('[data-testid="priority-dropdown"][data-state="open"]')).toBeVisible(); const highPriorityOption = page.locator('[data-testid="priority-option-high"]'); await expect(highPriorityOption).toBeVisible(); await highPriorityOption.click(); await expect(page.locator('[data-testid="priority-dropdown"][data-state="closed"]')).toBeVisible(); // Verify High is selected await expect(priorityDropdown).toContainText(/high/i); // Now clear the priority by selecting None await priorityDropdown.click(); await expect(page.locator('[data-testid="priority-dropdown"][data-state="open"]')).toBeVisible(); const nonePriorityOption = page.locator('[data-testid="priority-option-none"]'); await expect(nonePriorityOption).toBeVisible(); await nonePriorityOption.click(); await expect(page.locator('[data-testid="priority-dropdown"][data-state="closed"]')).toBeVisible(); // Verify None is now selected await expect(priorityDropdown).toContainText(/none/i); // Close modal without saving await page.keyboard.press('Escape'); await expect(page.locator('[data-testid="task-modal"]')).not.toBeVisible({ timeout: 5000 }); }); test('project priority can be set to None after being set to Medium', async ({ page, baseURL }) => { const appUrl = await login(page, baseURL); await navigateAndWait(page, appUrl + '/projects'); // Click the "Add Project" button const addProjectButton = page.locator('button[aria-label="Add Project"]'); await expect(addProjectButton).toBeVisible(); await addProjectButton.click(); // Wait for the Project Modal to appear await expect(page.locator('[data-testid="project-modal"]')).toBeVisible({ timeout: 10000 }); // Fill in the project name const projectName = createUniqueEntity('Priority Clear Project'); const nameInput = page.locator('[data-testid="project-name-input"]'); await nameInput.fill(projectName); // Expand priority section const prioritySectionButton = page.locator('button[title*="Priority"]').filter({ has: page.locator('svg') }); await expect(prioritySectionButton).toBeVisible(); await prioritySectionButton.click(); await page.waitForTimeout(300); // Set priority to Medium const priorityDropdown = page.locator('[data-testid="priority-dropdown"]'); await priorityDropdown.click(); await page.waitForTimeout(200); const mediumPriorityOption = page.locator('[data-testid="priority-option-medium"]'); await expect(mediumPriorityOption).toBeVisible(); await mediumPriorityOption.click(); await page.waitForTimeout(200); // Verify Medium is selected await expect(priorityDropdown).toContainText(/medium/i); // Now clear the priority by selecting None await priorityDropdown.click(); await page.waitForTimeout(200); const nonePriorityOption = page.locator('[data-testid="priority-option-none"]'); await expect(nonePriorityOption).toBeVisible(); await nonePriorityOption.click(); await page.waitForTimeout(200); // Verify None is now selected await expect(priorityDropdown).toContainText(/none/i); // Close modal without saving await page.keyboard.press('Escape'); // Handle discard changes dialog (appears because we filled in the project name) const discardButton = page.locator('[data-testid="discard-dialog-confirm"]'); await expect(discardButton).toBeVisible({ timeout: 5000 }); await discardButton.click(); await expect(page.locator('[data-testid="project-modal"]')).not.toBeVisible({ timeout: 5000 }); }); test('task created from inbox thought defaults to None priority', async ({ page, baseURL }) => { const appUrl = await login(page, baseURL); await navigateAndWait(page, appUrl + '/inbox'); // Create an inbox item const timestamp = Date.now(); const thoughtContent = `Test thought ${timestamp}`; // Click the Quick Inbox Capture button in the navbar await page.getByRole('button', { name: 'Quick Inbox Capture' }).click(); // Wait for the InboxModal to appear await expect(page.locator('input[name="text"]')).toBeVisible(); // Add the thought await page.locator('input[name="text"]').fill(thoughtContent); // Submit the form by pressing Enter await page.locator('input[name="text"]').press('Enter'); // Wait for the modal to close await expect(page.locator('input[name="text"]')).not.toBeVisible(); // Verify the thought appears in the inbox await expect(page.locator('text=' + thoughtContent)).toBeVisible(); // Find the inbox item container and hover to show convert buttons const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: thoughtContent }); await inboxItemContainer.hover(); // Click the "Convert to Task" button (clipboard icon with title="Create task") await inboxItemContainer.locator('button[title="Create task"]').click(); // Wait for the Task Modal to appear const taskNameInput = page.locator('[data-testid="task-name-input"]'); await expect(taskNameInput).toBeVisible({ timeout: 10000 }); // Verify the task name field is pre-filled with the thought content await expect(taskNameInput).toHaveValue(thoughtContent); // Wait for modal to be in idle state await expect(page.locator('[data-testid="task-modal"][data-state="idle"]')).toBeVisible(); // Click the priority section icon to expand the priority section const prioritySectionButton = page.locator('button[title*="Priority"]').filter({ has: page.locator('svg') }); await prioritySectionButton.click(); // Wait for priority section to be expanded await expect(page.locator('[data-testid="priority-section"][data-state="expanded"]')).toBeVisible(); // Check that the priority dropdown shows "None" const priorityDropdown = page.locator('[data-testid="priority-dropdown"]'); await expect(priorityDropdown).toBeVisible(); // The dropdown should contain "None" text await expect(priorityDropdown).toContainText(/none/i); // Close modal without saving await page.keyboard.press('Escape'); await expect(page.locator('[data-testid="task-modal"]')).not.toBeVisible({ timeout: 5000 }); });