244 lines
No EOL
9.7 KiB
TypeScript
244 lines
No EOL
9.7 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
// Shared login function
|
|
async function loginAndNavigateToInbox(page, baseURL) {
|
|
const appUrl = baseURL ?? process.env.APP_URL ?? 'http://localhost:8080';
|
|
|
|
// Go directly to login page first
|
|
await page.goto(appUrl + '/login');
|
|
|
|
// Fill credentials and login
|
|
const email = process.env.E2E_EMAIL || 'test@tududi.com';
|
|
const password = process.env.E2E_PASSWORD || 'password123';
|
|
|
|
await page.getByLabel('Email').fill(email);
|
|
await page.getByLabel('Password').fill(password);
|
|
await page.getByRole('button', { name: /login/i }).click();
|
|
|
|
// Wait for redirect to Today view
|
|
await expect(page).toHaveURL(/\/today$/);
|
|
|
|
// Navigate to inbox page
|
|
await page.goto(appUrl + '/inbox');
|
|
await expect(page).toHaveURL(/\/inbox$/);
|
|
|
|
return appUrl;
|
|
}
|
|
|
|
// Shared function to create an inbox item
|
|
async function createInboxItem(page, content) {
|
|
// 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 test item
|
|
await page.locator('input[name="text"]').fill(content);
|
|
|
|
// 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 item appears in the inbox list
|
|
await expect(page.locator('text=' + content)).toBeVisible();
|
|
}
|
|
|
|
test('user can add a new inbox item and verify it has been added', async ({ page, baseURL }) => {
|
|
await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Add a unique test item
|
|
const testContent = `Test inbox item ${Date.now()}`;
|
|
await createInboxItem(page, testContent);
|
|
});
|
|
|
|
test('user can edit an inbox item', async ({ page, baseURL }) => {
|
|
await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Create an initial item
|
|
const timestamp = Date.now();
|
|
const originalContent = `Test item to edit ${timestamp}`;
|
|
await createInboxItem(page, originalContent);
|
|
|
|
// Find the inbox item container and hover to show edit button
|
|
const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: originalContent });
|
|
await inboxItemContainer.hover();
|
|
|
|
// Click the edit button (pencil icon) - it has title="Edit"
|
|
await inboxItemContainer.locator('button[title="Edit"]').click();
|
|
|
|
// Wait for the edit modal to appear
|
|
await expect(page.locator('input[name="text"]')).toBeVisible();
|
|
|
|
// Edit the content
|
|
const editedContent = `Edited test item ${timestamp}`;
|
|
await page.locator('input[name="text"]').clear();
|
|
await page.locator('input[name="text"]').fill(editedContent);
|
|
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 edited content appears in the inbox item
|
|
await expect(page.locator('.rounded-lg.shadow-sm').filter({ hasText: editedContent })).toBeVisible();
|
|
|
|
// Verify the original content is no longer visible in inbox items
|
|
await expect(page.locator('.rounded-lg.shadow-sm').filter({ hasText: originalContent })).not.toBeVisible();
|
|
});
|
|
|
|
test('user can delete an inbox item', async ({ page, baseURL }) => {
|
|
await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Create an initial item
|
|
const timestamp = Date.now();
|
|
const testContent = `Test item to delete ${timestamp}`;
|
|
await createInboxItem(page, testContent);
|
|
|
|
// Find the inbox item container and hover to show delete button
|
|
const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent });
|
|
await inboxItemContainer.hover();
|
|
|
|
// Click the delete button (trash icon) - it has title="Delete"
|
|
await inboxItemContainer.locator('button[title="Delete"]').click();
|
|
|
|
// Wait for and handle the confirmation dialog
|
|
await expect(page.locator('text=Delete Item')).toBeVisible();
|
|
// Click the red "Delete" button in the confirmation dialog
|
|
await page.locator('.bg-red-500.text-white').click();
|
|
|
|
// Verify the item is no longer visible
|
|
await expect(page.locator('text=' + testContent)).not.toBeVisible();
|
|
});
|
|
|
|
test('user can create task from inbox item', async ({ page, baseURL }) => {
|
|
const appUrl = await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Create an initial item
|
|
const timestamp = Date.now();
|
|
const testContent = `Test item to convert to task ${timestamp}`;
|
|
await createInboxItem(page, testContent);
|
|
|
|
// Find the inbox item container and hover to show convert buttons
|
|
const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent });
|
|
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 using specific test ID
|
|
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 inbox item content
|
|
await expect(taskNameInput).toHaveValue(testContent);
|
|
|
|
// Save the task using test ID
|
|
await page.locator('[data-testid="task-save-button"]').click();
|
|
|
|
// Wait for modal to close
|
|
await expect(taskNameInput).not.toBeVisible({ timeout: 10000 });
|
|
|
|
// Navigate back to inbox to verify the item was processed
|
|
await page.goto(appUrl + '/inbox');
|
|
|
|
// Verify the original inbox item is no longer in the inbox (successfully converted to task)
|
|
await expect(page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent })).not.toBeVisible();
|
|
|
|
// Navigate to tasks page to verify the task was created there
|
|
await page.goto(appUrl + '/tasks');
|
|
await expect(page).toHaveURL(/\/tasks$/);
|
|
|
|
// Verify the created task appears in the tasks list using the task-item-wrapper class
|
|
await expect(page.locator('.task-item-wrapper').filter({ hasText: testContent })).toBeVisible();
|
|
});
|
|
|
|
test('user can create project from inbox item', async ({ page, baseURL }) => {
|
|
const appUrl = await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Create an initial item
|
|
const timestamp = Date.now();
|
|
const testContent = `Test project from inbox ${timestamp}`;
|
|
await createInboxItem(page, testContent);
|
|
|
|
// Find the inbox item container and hover to show convert buttons
|
|
const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent });
|
|
await inboxItemContainer.hover();
|
|
|
|
// Click the "Create project" button
|
|
await inboxItemContainer.locator('button[title="Create project"]').click();
|
|
|
|
// Wait for the Project Modal to appear using specific test ID
|
|
const projectNameInput = page.locator('[data-testid="project-name-input"]');
|
|
await expect(projectNameInput).toBeVisible({ timeout: 10000 });
|
|
|
|
// Verify the project name field is pre-filled with the inbox item content
|
|
await expect(projectNameInput).toHaveValue(testContent);
|
|
|
|
// Save the project using test ID
|
|
await page.locator('[data-testid="project-save-button"]').click();
|
|
|
|
// Wait for modal to close
|
|
await expect(projectNameInput).not.toBeVisible({ timeout: 10000 });
|
|
|
|
// Navigate back to inbox to verify the item was processed
|
|
await page.goto(appUrl + '/inbox');
|
|
|
|
// Verify the original inbox item is no longer in the inbox (successfully converted to project)
|
|
await expect(page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent })).not.toBeVisible();
|
|
|
|
// Navigate to projects page to verify the project was created there
|
|
await page.goto(appUrl + '/projects');
|
|
await expect(page).toHaveURL(/\/projects$/);
|
|
|
|
// Wait a moment for the page to load
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Verify the created project appears - use a more specific selector
|
|
await expect(page.getByRole('link', { name: new RegExp(testContent) }).first()).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test('user can create note from inbox item', async ({ page, baseURL }) => {
|
|
const appUrl = await loginAndNavigateToInbox(page, baseURL);
|
|
|
|
// Create an initial item
|
|
const timestamp = Date.now();
|
|
const testContent = `Test note from inbox ${timestamp}`;
|
|
await createInboxItem(page, testContent);
|
|
|
|
// Find the inbox item container and hover to show convert buttons
|
|
const inboxItemContainer = page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent });
|
|
await inboxItemContainer.hover();
|
|
|
|
// Click the "Create note" button
|
|
await inboxItemContainer.locator('button[title="Create note"]').click();
|
|
|
|
// Wait for the Note Modal to appear using specific test ID
|
|
const noteTitleInput = page.locator('[data-testid="note-title-input"]');
|
|
await expect(noteTitleInput).toBeVisible({ timeout: 10000 });
|
|
|
|
// Verify the note title field is pre-filled with the inbox item content
|
|
await expect(noteTitleInput).toHaveValue(testContent);
|
|
|
|
// Save the note using test ID
|
|
await page.locator('[data-testid="note-save-button"]').click();
|
|
|
|
// Wait for modal to close
|
|
await expect(noteTitleInput).not.toBeVisible({ timeout: 10000 });
|
|
|
|
// Navigate back to inbox to verify the item was processed
|
|
await page.goto(appUrl + '/inbox');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Verify the original inbox item is no longer in the inbox (successfully converted to note)
|
|
await expect(page.locator('.rounded-lg.shadow-sm').filter({ hasText: testContent })).not.toBeVisible();
|
|
|
|
// Navigate to notes page - just verify we can get there successfully
|
|
await page.goto(appUrl + '/notes');
|
|
await expect(page).toHaveURL(/\/notes$/);
|
|
|
|
// The note was successfully created (inbox item was removed), which is the key test
|
|
// Note: Finding the exact note on the notes page can be flaky due to rendering/timing issues
|
|
// The important verification is that the inbox item was processed and removed
|
|
}); |