From 06ad7a89a7815bb95063354922704a5393eb985a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 31 Dec 2025 10:40:32 -0800 Subject: [PATCH 1/2] chore: allow generating expectation after each step --- .../prompts/playwright-test-generate.md | 4 +- .../.claude/prompts/playwright-test-plan.md | 4 +- .../todomvc/specs/basic-operations.plan.md | 955 ++++++++---------- .../add-multiple-todos.spec.ts | 34 - .../add-single-valid-todo.spec.ts | 31 - .../add-todo-with-long-text.spec.ts | 17 - .../add-todo-with-special-characters.spec.ts | 20 - .../reject-empty-todo.spec.ts | 21 - .../reject-whitespace-only-todo.spec.ts | 31 - .../complete-multiple-todos.spec.ts | 38 - .../complete-single-todo.spec.ts | 27 - .../mark-all-as-complete.spec.ts | 27 - .../completing-todos/uncomplete-todo.spec.ts | 24 - .../unmark-all-as-complete.spec.ts | 37 - .../cancel-edit-with-escape.spec.ts | 24 - .../delete-todo-by-clearing-text.spec.ts | 24 - .../editing-todos/edit-completed-todo.spec.ts | 28 - .../edit-todo-successfully.spec.ts | 24 - .../todo-creation/add-multiple-todos.spec.ts | 41 + .../todo-creation/add-single-todo.spec.ts | 32 + .../add-todo-special-chars.spec.ts | 21 + .../todo-creation/prevent-empty-todo.spec.ts | 23 + .../prevent-whitespace-todo.spec.ts | 20 + .../playwright/src/mcp/test/plannerTools.ts | 24 +- 24 files changed, 562 insertions(+), 969 deletions(-) delete mode 100644 examples/todomvc/tests/adding-new-todos/add-multiple-todos.spec.ts delete mode 100644 examples/todomvc/tests/adding-new-todos/add-single-valid-todo.spec.ts delete mode 100644 examples/todomvc/tests/adding-new-todos/add-todo-with-long-text.spec.ts delete mode 100644 examples/todomvc/tests/adding-new-todos/add-todo-with-special-characters.spec.ts delete mode 100644 examples/todomvc/tests/adding-new-todos/reject-empty-todo.spec.ts delete mode 100644 examples/todomvc/tests/adding-new-todos/reject-whitespace-only-todo.spec.ts delete mode 100644 examples/todomvc/tests/completing-todos/complete-multiple-todos.spec.ts delete mode 100644 examples/todomvc/tests/completing-todos/complete-single-todo.spec.ts delete mode 100644 examples/todomvc/tests/completing-todos/mark-all-as-complete.spec.ts delete mode 100644 examples/todomvc/tests/completing-todos/uncomplete-todo.spec.ts delete mode 100644 examples/todomvc/tests/completing-todos/unmark-all-as-complete.spec.ts delete mode 100644 examples/todomvc/tests/editing-todos/cancel-edit-with-escape.spec.ts delete mode 100644 examples/todomvc/tests/editing-todos/delete-todo-by-clearing-text.spec.ts delete mode 100644 examples/todomvc/tests/editing-todos/edit-completed-todo.spec.ts delete mode 100644 examples/todomvc/tests/editing-todos/edit-todo-successfully.spec.ts create mode 100644 examples/todomvc/tests/todo-creation/add-multiple-todos.spec.ts create mode 100644 examples/todomvc/tests/todo-creation/add-single-todo.spec.ts create mode 100644 examples/todomvc/tests/todo-creation/add-todo-special-chars.spec.ts create mode 100644 examples/todomvc/tests/todo-creation/prevent-empty-todo.spec.ts create mode 100644 examples/todomvc/tests/todo-creation/prevent-whitespace-todo.spec.ts diff --git a/examples/todomvc/.claude/prompts/playwright-test-generate.md b/examples/todomvc/.claude/prompts/playwright-test-generate.md index 335e9fd8ad3c6..0b16c13468365 100644 --- a/examples/todomvc/.claude/prompts/playwright-test-generate.md +++ b/examples/todomvc/.claude/prompts/playwright-test-generate.md @@ -3,6 +3,6 @@ agent: playwright-test-generator description: Generate test plan --- -Generate tests for the test plan's bullet 1.1 Add item to card. +Generate tests for the test plan's bullet 1. Todo Creation -Test plan: `specs/coverage.plan.md` +Test plan: `specs/basic-operations.plan.md` diff --git a/examples/todomvc/.claude/prompts/playwright-test-plan.md b/examples/todomvc/.claude/prompts/playwright-test-plan.md index 1c1f3a18715e5..c293bdaa6fd36 100644 --- a/examples/todomvc/.claude/prompts/playwright-test-plan.md +++ b/examples/todomvc/.claude/prompts/playwright-test-plan.md @@ -3,7 +3,7 @@ agent: playwright-test-planner description: Create test plan --- -Create test plan for "add to cart" functionality of my app. +Create test plan for basic operations of my todo app. - Seed file: `tests/seed.spec.ts` -- Test plan: `specs/coverage.plan.md` +- Test plan: `specs/basic-operations.plan.md` diff --git a/examples/todomvc/specs/basic-operations.plan.md b/examples/todomvc/specs/basic-operations.plan.md index 192dde995b08c..dc06a8be5cc77 100644 --- a/examples/todomvc/specs/basic-operations.plan.md +++ b/examples/todomvc/specs/basic-operations.plan.md @@ -1,723 +1,578 @@ -# TodoMVC Application - Basic Operations Test Plan +# TodoMVC Basic Operations Test Plan ## Application Overview -The TodoMVC application is a React-based todo list manager accessible at https://demo.playwright.dev/todomvc. The application provides comprehensive task management functionality with the following features: - -- **Task Creation**: Add new todos via input field -- **Task Completion**: Mark individual todos as complete/incomplete via checkboxes -- **Task Editing**: Double-click to edit todo text inline -- **Task Deletion**: Remove individual todos via delete button -- **Bulk Operations**: Mark all todos as complete/incomplete and clear all completed todos -- **Filtering**: View todos by All, Active, or Completed status with URL routing support -- **Counter Display**: Real-time count of active (incomplete) todos -- **Input Validation**: Prevents empty or whitespace-only todos +TodoMVC is a single-page application that helps users manage their tasks. The application provides functionality to add, edit, complete, delete, and filter todos. Users can manage individual todos or perform bulk operations like marking all as complete or clearing all completed items. The interface includes a text input for adding new todos, a list view showing all todos with their completion status, filter buttons to view all/active/completed todos, and a footer displaying the count of active items. ## Test Scenarios -### 1. Adding New Todos +### 1. Todo Creation **Seed:** `tests/seed.spec.ts` -#### 1.1 Add Single Valid Todo - -**File:** `tests/adding-new-todos/add-single-valid-todo.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Click in the "What needs to be done?" input field -3. Type "Buy groceries" -4. Press Enter key - -**Expected Results:** -- Todo appears in the list with an unchecked checkbox -- Todo text displays as "Buy groceries" -- Counter shows "1 item left" -- Input field is cleared and ready for next entry -- "Mark all as complete" checkbox becomes visible - -#### 1.2 Add Multiple Todos +#### 1.1. Add a single todo -**File:** `tests/adding-new-todos/add-multiple-todos.spec.ts` +**File:** `tests/todo-creation/add-single-todo.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add first todo: "Buy groceries" (type and press Enter) -3. Add second todo: "Walk the dog" (type and press Enter) -4. Add third todo: "Read a book" (type and press Enter) + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list and input field 'What needs to be done?' is visible + 2. Type 'Buy groceries' into the input field + Expect: The text appears in the input field + 3. Press Enter to submit the todo + Expect: The todo 'Buy groceries' appears in the list and the input field is cleared -**Expected Results:** -- All three todos appear in the list in order of creation -- Each todo has an unchecked checkbox -- Counter shows "3 items left" (plural) -- Input field is cleared after each addition +**Post Conditions:** + - The todo counter shows '1 item left' + - The new todo is unchecked (active state) -#### 1.3 Reject Empty Todo +#### 1.2. Add multiple todos -**File:** `tests/adding-new-todos/reject-empty-todo.spec.ts` +**File:** `tests/todo-creation/add-multiple-todos.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Click in the "What needs to be done?" input field -3. Press Enter without typing any text + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add first todo 'Buy groceries' by typing and pressing Enter + Expect: The first todo appears in the list + 3. Add second todo 'Walk the dog' by typing and pressing Enter + Expect: The second todo appears in the list below the first + 4. Add third todo 'Read a book' by typing and pressing Enter + Expect: The third todo appears in the list below the second -**Expected Results:** -- No todo is added to the list -- Todo list remains empty -- Counter is not displayed -- Input field remains focused +**Post Conditions:** + - All three todos are visible in the list + - The todo counter shows '3 items left' + - All todos are in active (unchecked) state -#### 1.4 Reject Whitespace-Only Todo +#### 1.3. Prevent adding empty todo -**File:** `tests/adding-new-todos/reject-whitespace-only-todo.spec.ts` +**File:** `tests/todo-creation/prevent-empty-todo.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Click in the "What needs to be done?" input field -3. Type only spaces (e.g., " ") -4. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Click into the input field without typing anything and press Enter + Expect: No todo is added to the list -**Expected Results:** -- No todo is added to the list -- Todo list remains empty -- Counter is not displayed -- Input field is cleared +**Post Conditions:** + - The todo list remains empty + - The input field is still focused and empty -#### 1.5 Add Todo with Special Characters +#### 1.4. Prevent adding whitespace-only todo -**File:** `tests/adding-new-todos/add-todo-with-special-characters.spec.ts` +**File:** `tests/todo-creation/prevent-whitespace-todo.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Type "Test with special chars: @#$%^&*()" -3. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Type only spaces ' ' into the input field and press Enter + Expect: No todo is added to the list -**Expected Results:** -- Todo is successfully added -- Special characters are displayed correctly -- Counter shows "1 item left" +**Post Conditions:** + - The todo list remains empty + - The input field is cleared or shows the spaces -#### 1.6 Add Todo with Long Text +#### 1.5. Add todo with special characters -**File:** `tests/adding-new-todos/add-todo-with-long-text.spec.ts` +**File:** `tests/todo-creation/add-todo-special-chars.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Type a very long text (e.g., "This is a very long todo item to test the character limit and see how the application handles extremely long text inputs that might break the layout or cause other issues") -3. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Type 'Buy @groceries & supplies (urgent!)' into the input field and press Enter + Expect: The todo appears in the list with all special characters preserved -**Expected Results:** -- Todo is successfully added -- Long text is displayed (may wrap or truncate depending on design) -- Counter shows "1 item left" -- Layout remains intact +**Post Conditions:** + - The todo displays exactly as entered with special characters + - The todo counter shows '1 item left' -### 2. Completing Todos +### 2. Todo Completion **Seed:** `tests/seed.spec.ts` -#### 2.1 Complete Single Todo +#### 2.1. Mark a single todo as complete -**File:** `tests/completing-todos/complete-single-todo.spec.ts` +**File:** `tests/todo-completion/mark-single-complete.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Click the checkbox next to "Buy groceries" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list unchecked + 3. Click the checkbox next to 'Buy groceries' + Expect: The checkbox becomes checked and the todo text may show visual indication of completion (strikethrough or style change) -**Expected Results:** -- Checkbox becomes checked -- Todo text may show visual indication of completion (strikethrough or style change) -- Counter shows "0 items left" -- "Clear completed" button appears -- Delete button becomes visible on hover +**Post Conditions:** + - The todo counter shows '0 items left' + - The 'Clear completed' button appears in the footer -#### 2.2 Complete Multiple Todos +#### 2.2. Unmark a completed todo -**File:** `tests/completing-todos/complete-multiple-todos.spec.ts` +**File:** `tests/todo-completion/unmark-completed.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Click the checkbox next to "Buy groceries" -4. Click the checkbox next to "Read a book" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list unchecked + 3. Click the checkbox to mark it as complete + Expect: The checkbox becomes checked + 4. Click the checkbox again to unmark it + Expect: The checkbox becomes unchecked and the todo returns to active state -**Expected Results:** -- Both selected todos show as completed -- Counter shows "1 item left" (only "Walk the dog" remaining) -- "Clear completed" button appears -- One todo remains active +**Post Conditions:** + - The todo counter shows '1 item left' + - The 'Clear completed' button is no longer visible -#### 2.3 Uncomplete Todo +#### 2.3. Mark all todos as complete -**File:** `tests/completing-todos/uncomplete-todo.spec.ts` +**File:** `tests/todo-completion/mark-all-complete.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Click the checkbox to complete it -4. Click the checkbox again to uncomplete it + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list unchecked + 3. Click the '❯Mark all as complete' checkbox at the top of the list + Expect: All three todos become checked -**Expected Results:** -- Checkbox becomes unchecked -- Todo returns to active state -- Counter shows "1 item left" -- "Clear completed" button disappears +**Post Conditions:** + - The todo counter shows '0 items left' + - The 'Clear completed' button appears + - The '❯Mark all as complete' checkbox is checked -#### 2.4 Mark All as Complete +#### 2.4. Unmark all completed todos -**File:** `tests/completing-todos/mark-all-as-complete.spec.ts` +**File:** `tests/todo-completion/unmark-all-complete.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Click the "Mark all as complete" checkbox (chevron icon) + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Click the '❯Mark all as complete' checkbox to mark all as complete + Expect: All todos become checked + 4. Click the '❯Mark all as complete' checkbox again + Expect: All todos become unchecked -**Expected Results:** -- All todos show as completed -- All individual checkboxes are checked -- "Mark all as complete" checkbox is checked -- Counter shows "0 items left" -- "Clear completed" button appears +**Post Conditions:** + - The todo counter shows '3 items left' + - The 'Clear completed' button is no longer visible + - The '❯Mark all as complete' checkbox is unchecked -#### 2.5 Unmark All as Complete +#### 2.5. Mixed completion state -**File:** `tests/completing-todos/unmark-all-as-complete.spec.ts` +**File:** `tests/todo-completion/mixed-completion.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Click the "Mark all as complete" checkbox to complete all -4. Click the "Mark all as complete" checkbox again + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Mark 'Buy groceries' as complete + Expect: First todo is checked + 4. Mark 'Read a book' as complete + Expect: Third todo is checked -**Expected Results:** -- All todos return to active state -- All individual checkboxes are unchecked -- "Mark all as complete" checkbox is unchecked -- Counter shows "3 items left" -- "Clear completed" button disappears +**Post Conditions:** + - The todo counter shows '1 item left' + - The 'Clear completed' button is visible + - 'Walk the dog' remains unchecked + - The '❯Mark all as complete' checkbox is unchecked (since not all are complete) -### 3. Editing Todos +### 3. Todo Editing **Seed:** `tests/seed.spec.ts` -#### 3.1 Edit Todo Successfully +#### 3.1. Edit todo text -**File:** `tests/editing-todos/edit-todo-successfully.spec.ts` +**File:** `tests/todo-editing/edit-todo-text.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Double-click on the todo text "Buy groceries" -4. Clear the existing text -5. Type "Buy groceries and milk" -6. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Double-click on the todo text 'Buy groceries' + Expect: The todo enters edit mode with a text input showing 'Buy groceries' + 4. Clear the text and type 'Buy groceries and milk' + Expect: The new text appears in the edit field + 5. Press Enter to save the changes + Expect: The todo exits edit mode and displays 'Buy groceries and milk' -**Expected Results:** -- Todo enters edit mode (input field appears) -- Original text is pre-populated in the edit field -- After pressing Enter, todo text updates to "Buy groceries and milk" -- Todo exits edit mode -- Todo remains in the same state (active/completed) +**Post Conditions:** + - The todo shows the updated text + - The todo remains in its original completion state -#### 3.2 Cancel Edit with Escape +#### 3.2. Cancel editing with Escape -**File:** `tests/editing-todos/cancel-edit-with-escape.spec.ts` +**File:** `tests/todo-editing/cancel-edit-escape.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Double-click on the todo text -4. Type "Changed text" -5. Press Escape key + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Double-click on the todo text to enter edit mode + Expect: The edit input appears with 'Buy groceries' + 4. Change the text to 'Something else' + Expect: The new text appears in the edit field + 5. Press Escape key + Expect: The edit is cancelled and the original text 'Buy groceries' is preserved -**Expected Results:** -- Todo exits edit mode -- Original text "Buy groceries" is preserved -- Changes are discarded -- Todo remains in the same state +**Post Conditions:** + - The todo shows the original text 'Buy groceries' + - The todo is no longer in edit mode -#### 3.3 Delete Todo by Clearing Text +#### 3.3. Delete todo by clearing text -**File:** `tests/editing-todos/delete-todo-by-clearing-text.spec.ts` +**File:** `tests/todo-editing/delete-by-clearing.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Double-click on the todo text -4. Clear all text (delete all characters) -5. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Double-click on the todo text to enter edit mode + Expect: The edit input appears + 4. Clear all the text in the edit field + Expect: The edit field is empty + 5. Press Enter to save + Expect: The todo is removed from the list -**Expected Results:** -- Todo is removed from the list -- Counter decrements appropriately -- If no todos remain, counter and controls disappear +**Post Conditions:** + - The todo list is empty + - The todo counter and footer controls are hidden -#### 3.4 Edit Completed Todo +#### 3.4. Edit completed todo -**File:** `tests/editing-todos/edit-completed-todo.spec.ts` +**File:** `tests/todo-editing/edit-completed-todo.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Click the checkbox to complete it -4. Double-click on the todo text -5. Type "Buy groceries and milk" -6. Press Enter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Mark the todo as complete by clicking its checkbox + Expect: The todo is marked as complete + 4. Double-click on the completed todo text + Expect: The todo enters edit mode + 5. Change the text to 'Buy groceries and milk' and press Enter + Expect: The todo text is updated -**Expected Results:** -- Todo enters edit mode -- Todo text is successfully updated -- Todo remains in completed state after editing -- Checkbox remains checked +**Post Conditions:** + - The todo shows the updated text 'Buy groceries and milk' + - The todo remains in completed state (checked) -### 4. Deleting Todos +### 4. Todo Deletion **Seed:** `tests/seed.spec.ts` -#### 4.1 Delete Single Active Todo +#### 4.1. Delete a single todo -**File:** `tests/deleting-todos/delete-single-active-todo.spec.ts` +**File:** `tests/todo-deletion/delete-single-todo.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Hover over the todo to reveal the delete button -4. Click the delete button (×) + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Hover over the todo to reveal the delete button (×) + Expect: The delete button becomes visible + 4. Click the delete button (×) + Expect: The todo is removed from the list -**Expected Results:** -- Todo is immediately removed from the list -- Counter decrements to "0 items left" or disappears -- Todo list controls disappear if no todos remain +**Post Conditions:** + - The todo list is empty + - The footer and counter are hidden -#### 4.2 Delete Single Completed Todo +#### 4.2. Delete todo from multiple todos -**File:** `tests/deleting-todos/delete-single-completed-todo.spec.ts` +**File:** `tests/todo-deletion/delete-from-multiple.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Click the checkbox to complete it -4. Hover over the todo to reveal the delete button -5. Click the delete button (×) + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Hover over 'Walk the dog' to reveal the delete button + Expect: The delete button becomes visible for 'Walk the dog' + 4. Click the delete button for 'Walk the dog' + Expect: The 'Walk the dog' todo is removed -**Expected Results:** -- Todo is immediately removed from the list -- "Clear completed" button disappears -- Todo list controls disappear if no todos remain +**Post Conditions:** + - Only 'Buy groceries' and 'Read a book' remain in the list + - The todo counter shows '2 items left' -#### 4.3 Delete Multiple Todos Individually +#### 4.3. Clear all completed todos -**File:** `tests/deleting-todos/delete-multiple-todos-individually.spec.ts` +**File:** `tests/todo-deletion/clear-completed.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Delete "Walk the dog" by clicking its delete button -4. Delete "Buy groceries" by clicking its delete button + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Mark 'Buy groceries' and 'Read a book' as complete + Expect: Two todos are checked + 4. Click the 'Clear completed' button in the footer + Expect: The completed todos are removed from the list -**Expected Results:** -- After first deletion, counter shows "2 items left" -- After second deletion, counter shows "1 item left" -- Only "Read a book" remains in the list +**Post Conditions:** + - Only 'Walk the dog' remains in the list + - The todo counter shows '1 item left' + - The 'Clear completed' button is no longer visible -#### 4.4 Clear All Completed Todos +#### 4.4. Clear completed when all are completed -**File:** `tests/deleting-todos/clear-all-completed-todos.spec.ts` +**File:** `tests/todo-deletion/clear-all-completed.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Buy groceries" and "Walk the dog" by clicking their checkboxes -4. Click the "Clear completed" button + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add two todos: 'Buy groceries', 'Walk the dog' + Expect: Both todos appear in the list + 3. Mark both todos as complete + Expect: Both todos are checked + 4. Click the 'Clear completed' button + Expect: All todos are removed -**Expected Results:** -- Both completed todos are removed from the list -- Only "Read a book" (active) remains -- Counter shows "1 item left" -- "Clear completed" button disappears +**Post Conditions:** + - The todo list is empty + - The footer and counter are hidden + - Only the input field remains visible -#### 4.5 Clear Completed When All Are Completed +#### 4.5. Delete completed todo individually -**File:** `tests/deleting-todos/clear-completed-when-all-are-completed.spec.ts` +**File:** `tests/todo-deletion/delete-completed-individually.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Click "Mark all as complete" checkbox -4. Click "Clear completed" button + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The todo appears in the list + 3. Mark the todo as complete + Expect: The todo is checked + 4. Hover over the completed todo and click the delete button (×) + Expect: The completed todo is removed -**Expected Results:** -- All todos are removed from the list -- Todo list becomes empty -- Counter and controls disappear -- Only the input field remains visible +**Post Conditions:** + - The todo list is empty + - The footer is hidden -### 5. Filtering Todos +### 5. Todo Filtering **Seed:** `tests/seed.spec.ts` -#### 5.1 View All Todos (Default) - -**File:** `tests/filtering-todos/view-all-todos-default.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Walk the dog" by clicking its checkbox -4. Verify the "All" filter is selected by default - -**Expected Results:** -- All three todos are visible (both active and completed) -- "All" link appears selected/highlighted -- URL shows "/#/" or "/#" -- Counter shows "2 items left" +#### 5.1. View all todos -#### 5.2 Filter Active Todos - -**File:** `tests/filtering-todos/filter-active-todos.spec.ts` +**File:** `tests/todo-filtering/view-all-todos.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Walk the dog" by clicking its checkbox -4. Click the "Active" filter link + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Mark 'Buy groceries' as complete + Expect: First todo is checked + 4. Click the 'All' filter link + Expect: All three todos (both active and completed) are visible -**Expected Results:** -- Only active todos are visible ("Buy groceries" and "Read a book") -- Completed todo "Walk the dog" is hidden -- "Active" link appears selected/highlighted -- URL changes to "/#/active" -- Counter shows "2 items left" +**Post Conditions:** + - All three todos are visible in the list + - The 'All' filter link is highlighted/active + - The URL hash is '#/' or empty -#### 5.3 Filter Completed Todos +#### 5.2. View active todos only -**File:** `tests/filtering-todos/filter-completed-todos.spec.ts` +**File:** `tests/todo-filtering/view-active-todos.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Walk the dog" and "Buy groceries" by clicking their checkboxes -4. Click the "Completed" filter link + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Mark 'Buy groceries' as complete + Expect: First todo is checked + 4. Click the 'Active' filter link + Expect: Only 'Walk the dog' and 'Read a book' are visible -**Expected Results:** -- Only completed todos are visible ("Walk the dog" and "Buy groceries") -- Active todo "Read a book" is hidden -- "Completed" link appears selected/highlighted -- URL changes to "/#/completed" -- Counter still shows "1 item left" (total active count) -- "Clear completed" button is visible +**Post Conditions:** + - Only unchecked todos are visible + - The 'Active' filter link is highlighted/active + - The URL hash is '#/active' + - The todo counter still shows the correct count of active items -#### 5.4 Switch Between Filters +#### 5.3. View completed todos only -**File:** `tests/filtering-todos/switch-between-filters.spec.ts` +**File:** `tests/todo-filtering/view-completed-todos.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Walk the dog" -4. Click "Active" filter -5. Click "Completed" filter -6. Click "All" filter + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear in the list + 3. Mark 'Buy groceries' and 'Read a book' as complete + Expect: Two todos are checked + 4. Click the 'Completed' filter link + Expect: Only 'Buy groceries' and 'Read a book' are visible -**Expected Results:** -- Each filter shows appropriate todos -- Filter selection updates correctly -- URL updates with each filter change -- Counter remains consistent across filter changes +**Post Conditions:** + - Only checked todos are visible + - The 'Completed' filter link is highlighted/active + - The URL hash is '#/completed' + - The 'Clear completed' button is visible -#### 5.5 Add Todo While Filtered +#### 5.4. Switch between filters -**File:** `tests/filtering-todos/add-todo-while-filtered.spec.ts` +**File:** `tests/todo-filtering/switch-filters.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Complete it by clicking its checkbox -4. Click "Active" filter (should show no todos) -5. Add a new todo: "Walk the dog" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: All three todos appear + 3. Mark 'Buy groceries' as complete + Expect: First todo is checked + 4. Click 'Active' filter + Expect: Only active todos are shown (2 todos) + 5. Click 'Completed' filter + Expect: Only completed todos are shown (1 todo) + 6. Click 'All' filter + Expect: All todos are shown again (3 todos) -**Expected Results:** -- New todo appears in the list (as it's active) -- Counter updates to "1 item left" -- Todo is visible because it matches the active filter +**Post Conditions:** + - The filter switches correctly each time + - The appropriate filter link is highlighted + - The URL hash updates accordingly -#### 5.6 Complete Todo While on Active Filter +#### 5.5. Filter with no matching todos -**File:** `tests/filtering-todos/complete-todo-while-on-active-filter.spec.ts` +**File:** `tests/todo-filtering/filter-no-matches.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add two todos: "Buy groceries" and "Walk the dog" -3. Click "Active" filter -4. Complete "Buy groceries" by clicking its checkbox + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add two todos: 'Buy groceries', 'Walk the dog' + Expect: Both todos appear in the list unchecked + 3. Click the 'Completed' filter link + Expect: No todos are visible (empty list area) -**Expected Results:** -- "Buy groceries" disappears from the active view -- Only "Walk the dog" remains visible -- Counter updates to "1 item left" -- Completed todo is not deleted, just filtered out +**Post Conditions:** + - The main todo list area is empty or shows no items + - The footer with filters is still visible + - The 'Completed' filter link is highlighted -#### 5.7 Delete Todo While Filtered +#### 5.6. Complete todo while viewing active filter -**File:** `tests/filtering-todos/delete-todo-while-filtered.spec.ts` +**File:** `tests/todo-filtering/complete-in-active-view.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add two todos: "Buy groceries" and "Walk the dog" -3. Complete "Buy groceries" -4. Click "Completed" filter -5. Delete "Buy groceries" using the delete button + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add two todos: 'Buy groceries', 'Walk the dog' + Expect: Both todos appear in the list + 3. Click the 'Active' filter link + Expect: Both todos are visible + 4. Mark 'Buy groceries' as complete + Expect: The 'Buy groceries' todo disappears from the active view -**Expected Results:** -- "Buy groceries" is removed from the list -- Completed filter shows no todos -- Counter shows "1 item left" (for the active todo) -- "Clear completed" button disappears +**Post Conditions:** + - Only 'Walk the dog' is visible in the active view + - The todo counter shows '1 item left' + - Switching to 'All' or 'Completed' shows 'Buy groceries' is still there and checked -### 6. Counter Display +### 6. Todo Counter **Seed:** `tests/seed.spec.ts` -#### 6.1 Counter Shows Correct Singular Form +#### 6.1. Counter updates when adding todos -**File:** `tests/counter-display/counter-shows-singular-form.spec.ts` +**File:** `tests/todo-counter/counter-add.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add a single todo: "Buy groceries" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add a todo 'Buy groceries' + Expect: The counter shows '1 item left' + 3. Add a todo 'Walk the dog' + Expect: The counter shows '2 items left' + 4. Add a todo 'Read a book' + Expect: The counter shows '3 items left' -**Expected Results:** -- Counter displays "1 item left" (singular "item") +**Post Conditions:** + - The counter accurately reflects the number of active todos + - The counter uses plural 'items' when count is not 1 -#### 6.2 Counter Shows Correct Plural Form +#### 6.2. Counter updates when completing todos -**File:** `tests/counter-display/counter-shows-plural-form.spec.ts` +**File:** `tests/todo-counter/counter-complete.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add two todos: "Buy groceries" and "Walk the dog" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: The counter shows '3 items left' + 3. Mark 'Buy groceries' as complete + Expect: The counter shows '2 items left' + 4. Mark 'Walk the dog' as complete + Expect: The counter shows '1 item left' + 5. Mark 'Read a book' as complete + Expect: The counter shows '0 items left' -**Expected Results:** -- Counter displays "2 items left" (plural "items") +**Post Conditions:** + - The counter decreases as todos are completed + - The counter uses singular 'item' when count is 1 -#### 6.3 Counter Updates When Completing Todo +#### 6.3. Counter updates when deleting todos -**File:** `tests/counter-display/counter-updates-when-completing.spec.ts` +**File:** `tests/todo-counter/counter-delete.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add three todos: "Buy groceries", "Walk the dog", "Read a book" -3. Complete "Walk the dog" -4. Complete "Buy groceries" + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: The counter shows '3 items left' + 3. Delete 'Walk the dog' using the delete button (×) + Expect: The counter shows '2 items left' -**Expected Results:** -- Initially shows "3 items left" -- After first completion shows "2 items left" -- After second completion shows "1 item left" +**Post Conditions:** + - The counter decreases when an active todo is deleted -#### 6.4 Counter Shows Zero When All Completed +#### 6.4. Counter unchanged when deleting completed todo -**File:** `tests/counter-display/counter-shows-zero-when-all-completed.spec.ts` +**File:** `tests/todo-counter/counter-delete-completed.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Add two todos: "Buy groceries" and "Walk the dog" -3. Click "Mark all as complete" checkbox - -**Expected Results:** -- Counter displays "0 items left" -- Counter remains visible even at zero + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add two todos: 'Buy groceries', 'Walk the dog' + Expect: The counter shows '2 items left' + 3. Mark 'Buy groceries' as complete + Expect: The counter shows '1 item left' + 4. Delete 'Buy groceries' using the delete button + Expect: The counter still shows '1 item left' -### 7. UI Controls Visibility +**Post Conditions:** + - The counter only counts active (uncompleted) todos + - Deleting completed todos doesn't affect the counter -**Seed:** `tests/seed.spec.ts` - -#### 7.1 Controls Hidden When No Todos +#### 6.5. Counter persists across filter views -**File:** `tests/ui-controls-visibility/controls-hidden-when-no-todos.spec.ts` +**File:** `tests/todo-counter/counter-across-filters.spec.ts` **Steps:** -1. Navigate to the TodoMVC application -2. Verify the initial state with no todos - -**Expected Results:** -- "Mark all as complete" checkbox is not visible -- Counter is not displayed -- Filter links are not displayed -- Only the input field and header are visible - -#### 7.2 Controls Appear When First Todo Added - -**File:** `tests/ui-controls-visibility/controls-appear-when-first-todo-added.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" - -**Expected Results:** -- "Mark all as complete" checkbox becomes visible -- Counter appears showing "1 item left" -- Filter links (All/Active/Completed) appear -- Footer with controls is displayed - -#### 7.3 Controls Disappear When Last Todo Removed - -**File:** `tests/ui-controls-visibility/controls-disappear-when-last-todo-removed.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Delete it using the delete button - -**Expected Results:** -- All controls disappear -- View returns to initial empty state -- Only input field remains visible - -#### 7.4 Clear Completed Button Visibility - -**File:** `tests/ui-controls-visibility/clear-completed-button-visibility.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add two todos: "Buy groceries" and "Walk the dog" -3. Complete "Buy groceries" -4. Complete "Walk the dog" -5. Uncomplete "Walk the dog" - -**Expected Results:** -- "Clear completed" button appears after first completion -- Button remains visible while at least one todo is completed -- Button disappears when no todos are completed - -### 8. Edge Cases and Error Handling + 1. Navigate to the TodoMVC application + Expect: The page loads with an empty todo list + 2. Add three todos: 'Buy groceries', 'Walk the dog', 'Read a book' + Expect: The counter shows '3 items left' + 3. Mark 'Buy groceries' as complete + Expect: The counter shows '2 items left' + 4. Click 'Active' filter + Expect: The counter still shows '2 items left' + 5. Click 'Completed' filter + Expect: The counter still shows '2 items left' -**Seed:** `tests/seed.spec.ts` - -#### 8.1 Rapidly Add Multiple Todos - -**File:** `tests/edge-cases/rapidly-add-multiple-todos.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Quickly add 10 todos by typing and pressing Enter rapidly - -**Expected Results:** -- All 10 todos are successfully added -- Counter shows "10 items left" -- Todos appear in the order they were added -- No todos are lost or duplicated - -#### 8.2 Rapidly Toggle Todo Completion - -**File:** `tests/edge-cases/rapidly-toggle-todo-completion.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Rapidly click the checkbox multiple times (5-10 clicks) - -**Expected Results:** -- Todo state toggles correctly with each click -- Final state is predictable (checked or unchecked) -- Counter updates correctly -- No UI glitches occur - -#### 8.3 Edit During Filter View - -**File:** `tests/edge-cases/edit-during-filter-view.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Click "Active" filter -4. Double-click to edit the todo -5. Change text to "Buy groceries and milk" -6. Press Enter - -**Expected Results:** -- Todo successfully enters edit mode -- Edit is saved correctly -- Todo remains visible in Active filter -- No filter state is lost - -#### 8.4 Navigate Directly to Filtered URL - -**File:** `tests/edge-cases/navigate-directly-to-filtered-url.spec.ts` - -**Steps:** -1. Navigate directly to "https://demo.playwright.dev/todomvc/#/active" -2. Add a todo: "Buy groceries" -3. Complete it - -**Expected Results:** -- Application loads with Active filter pre-selected -- New active todo is visible -- When completed, todo disappears from view -- Filter state is maintained - -#### 8.5 Multiple Browser Tabs (Session Isolation) - -**File:** `tests/edge-cases/multiple-browser-tabs-session-isolation.spec.ts` - -**Steps:** -1. Open TodoMVC in first tab -2. Add a todo: "Buy groceries" in first tab -3. Open TodoMVC in second tab -4. Verify todo list in second tab - -**Expected Results:** -- Second tab either shows the same todo (if using persistence) or starts empty (if session-based) -- Each tab operates independently without conflicts -- No errors occur from multiple instances - -#### 8.6 Hover States Work Correctly - -**File:** `tests/edge-cases/hover-states-work-correctly.spec.ts` - -**Steps:** -1. Navigate to the TodoMVC application -2. Add a todo: "Buy groceries" -3. Hover over the todo item -4. Move mouse away - -**Expected Results:** -- Delete button (×) appears on hover -- Delete button disappears when not hovering -- Hover state does not interfere with editing or clicking - -## Testing Notes - -### Assumptions -- All tests assume a fresh/blank application state at the start (provided by seed file) -- Tests are designed to be independent and can run in any order -- No persistence testing is included (refresh behavior not covered) - -### Browser Compatibility -- Tests should be run across all major browsers (Chromium, Firefox, WebKit) -- UI controls may have slight visual differences across browsers - -### Performance Considerations -- Application should handle at least 100 todos without performance degradation -- Filtering should be instantaneous even with many todos -- No memory leaks should occur with repeated operations - -### Accessibility Considerations -- All interactive elements should be keyboard accessible -- Screen readers should announce todo state changes -- Focus management should be logical during editing - -## Test Coverage Summary - -This test plan covers: -- **47 individual test scenarios** across 8 major functional areas -- Happy path scenarios for all core features -- Edge cases and boundary conditions -- Input validation and error prevention -- UI state management and visibility -- Filter functionality and URL routing -- Counter accuracy and formatting -- Bulk operations and individual actions - -Each test is independent, clearly documented, and designed for automation using Playwright. +**Post Conditions:** + - The counter always shows the count of active todos regardless of the current filter view diff --git a/examples/todomvc/tests/adding-new-todos/add-multiple-todos.spec.ts b/examples/todomvc/tests/adding-new-todos/add-multiple-todos.spec.ts deleted file mode 100644 index 234cdb43f09a3..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/add-multiple-todos.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -// spec: Adding New Todos - should add multiple todos -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should add multiple todos', async ({ page }) => { - // Add first todo: "Buy groceries" (type and press Enter) - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add second todo: "Walk the dog" (type and press Enter) - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Walk the dog'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add third todo: "Read a book" (type and press Enter) - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Read a book'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Verify all three todos appear in the list in order of creation - await expect(page.locator('body')).toMatchAriaSnapshot(` -- list: - - listitem: "Buy groceries" - - listitem: "Walk the dog" - - listitem: "Read a book" -`); - - // Verify counter shows "3 items left" (plural) - await expect(page.getByText('3 items left')).toBeVisible(); - - // Verify input field is cleared after each addition - await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue(''); - }); -}); diff --git a/examples/todomvc/tests/adding-new-todos/add-single-valid-todo.spec.ts b/examples/todomvc/tests/adding-new-todos/add-single-valid-todo.spec.ts deleted file mode 100644 index 5ba7c100a8a8c..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/add-single-valid-todo.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should add single valid todo', async ({ page }) => { - // Click in the "What needs to be done?" input field - await page.getByRole('textbox', { name: 'What needs to be done?' }).click(); - - // Type "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - - // Press Enter key - await page.keyboard.press('Enter'); - - // Todo appears in the list with an unchecked checkbox - await expect(page.getByTestId('todo-item')).toBeVisible(); - - // Todo text displays as "Buy groceries" - await expect(page.getByText('Buy groceries')).toBeVisible(); - - // Counter shows "1 item left" - await expect(page.getByText('1 item left')).toBeVisible(); - - // Input field is cleared and ready for next entry - await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue(''); - - // "Mark all as complete" checkbox becomes visible - await expect(page.getByRole('checkbox', { name: '❯Mark all as complete' })).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/adding-new-todos/add-todo-with-long-text.spec.ts b/examples/todomvc/tests/adding-new-todos/add-todo-with-long-text.spec.ts deleted file mode 100644 index b0297040fe08c..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/add-todo-with-long-text.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should add todo with long text', async ({ page }) => { - // Type a very long text (e.g., "This is a very long todo item to test the character limit and see how the application handles extremely long text inputs that might break the layout or cause other issues") - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('This is a very long todo item to test the character limit and see how the application handles extremely long text inputs that might break the layout or cause other issues'); - - // Press Enter - await page.keyboard.press('Enter'); - - // Todo is successfully added - Long text is displayed (may wrap or truncate depending on design) - await expect(page.getByText('This is a very long todo item to test the character limit and see how the application handles extremely long text inputs that might break the layout or cause other issues')).toBeVisible(); - - // Counter shows "1 item left" - await expect(page.getByText('1 item left')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/adding-new-todos/add-todo-with-special-characters.spec.ts b/examples/todomvc/tests/adding-new-todos/add-todo-with-special-characters.spec.ts deleted file mode 100644 index 0850735af5cbc..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/add-todo-with-special-characters.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -// spec: Adding New Todos - should add todo with special characters -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should add todo with special characters', async ({ page }) => { - // Type "Test with special chars: @#$%^&*()" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Test with special chars: @#$%^&*()'); - - // Press Enter - await page.keyboard.press('Enter'); - - // Verify todo is successfully added and special characters are displayed correctly - await expect(page.getByText('Test with special chars: @#$%^&*()')).toBeVisible(); - - // Verify counter shows "1 item left" - await expect(page.getByText('1 item left')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/adding-new-todos/reject-empty-todo.spec.ts b/examples/todomvc/tests/adding-new-todos/reject-empty-todo.spec.ts deleted file mode 100644 index 74edbeb2b6474..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/reject-empty-todo.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -// spec: Adding New Todos -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should reject empty todo', async ({ page }) => { - // Click in the "What needs to be done?" input field - await page.getByRole('textbox', { name: 'What needs to be done?' }).click(); - - // Press Enter without typing any text - await page.keyboard.press('Enter'); - - // Verify no todo is added to the list and counter is not displayed - await expect(page.locator('.todo-list')).not.toBeVisible(); - await expect(page.locator('.todo-count')).not.toBeVisible(); - - // Verify input field remains focused - await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeFocused(); - }); -}); diff --git a/examples/todomvc/tests/adding-new-todos/reject-whitespace-only-todo.spec.ts b/examples/todomvc/tests/adding-new-todos/reject-whitespace-only-todo.spec.ts deleted file mode 100644 index 3267557aaac45..0000000000000 --- a/examples/todomvc/tests/adding-new-todos/reject-whitespace-only-todo.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -// spec: Adding New Todos -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Adding New Todos', () => { - test('should reject whitespace-only todo', async ({ page }) => { - // 1. Navigate to the TodoMVC application - // (handled by seed) - - // 2. Click in the "What needs to be done?" input field - await page.getByRole('textbox', { name: 'What needs to be done?' }).click(); - - // 3. Type only spaces (e.g., " ") - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill(' '); - - // 4. Press Enter - await page.keyboard.press('Enter'); - - // Expected Results: - // - No todo is added to the list - // - Todo list remains empty - await expect(page.getByRole('list')).not.toBeVisible(); - - // - Counter is not displayed - await expect(page.getByText(/\d+ items? left/)).not.toBeVisible(); - - // - Input field retains the whitespace (application doesn't clear it) - await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue(' '); - }); -}); diff --git a/examples/todomvc/tests/completing-todos/complete-multiple-todos.spec.ts b/examples/todomvc/tests/completing-todos/complete-multiple-todos.spec.ts deleted file mode 100644 index d3dd381e87608..0000000000000 --- a/examples/todomvc/tests/completing-todos/complete-multiple-todos.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { test, expect } from '../fixtures'; - -test.describe('Completing Todos', () => { - test('should complete multiple todos', async ({ page }) => { - // Add first todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add second todo: "Walk the dog" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Walk the dog'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add third todo: "Read a book" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Read a book'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the checkbox next to "Buy groceries" - await page.getByRole('listitem').filter({ hasText: 'Buy groceries' }).getByLabel('Toggle Todo').click(); - - // Click the checkbox next to "Read a book" - await page.getByRole('listitem').filter({ hasText: 'Read a book' }).getByLabel('Toggle Todo').click(); - - // Verify "Buy groceries" is completed - await expect(page.getByRole('listitem').filter({ hasText: 'Buy groceries' }).getByLabel('Toggle Todo')).toBeChecked(); - - // Verify "Read a book" is completed - await expect(page.getByRole('listitem').filter({ hasText: 'Read a book' }).getByLabel('Toggle Todo')).toBeChecked(); - - // Verify counter shows "1 item left" - await expect(page.getByText('1 item left')).toBeVisible(); - - // Verify "Clear completed" button appears - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); - - // Verify "Walk the dog" remains active (unchecked) - await expect(page.getByRole('listitem').filter({ hasText: 'Walk the dog' }).getByLabel('Toggle Todo')).not.toBeChecked(); - }); -}); diff --git a/examples/todomvc/tests/completing-todos/complete-single-todo.spec.ts b/examples/todomvc/tests/completing-todos/complete-single-todo.spec.ts deleted file mode 100644 index dee8cb196690b..0000000000000 --- a/examples/todomvc/tests/completing-todos/complete-single-todo.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -// spec: Completing Todos - should complete single todo -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Completing Todos', () => { - test('should complete single todo', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the checkbox next to "Buy groceries" - await page.getByRole('checkbox', { name: 'Toggle Todo' }).click(); - - // Verify checkbox becomes checked - await expect(page.getByRole('checkbox', { name: 'Toggle Todo' })).toBeChecked(); - - // Verify counter shows "0 items left" - await expect(page.getByText('0 items left')).toBeVisible(); - - // Verify "Clear completed" button appears - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); - - // Verify delete button becomes visible - await expect(page.getByRole('button', { name: 'Delete' })).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/completing-todos/mark-all-as-complete.spec.ts b/examples/todomvc/tests/completing-todos/mark-all-as-complete.spec.ts deleted file mode 100644 index 363d7c2d8fa67..0000000000000 --- a/examples/todomvc/tests/completing-todos/mark-all-as-complete.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Completing Todos', () => { - test('should mark all as complete', async ({ page }) => { - // Add three todos: "Buy groceries", "Walk the dog", "Read a book" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Walk the dog'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Read a book'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the "Mark all as complete" checkbox (chevron icon) - await page.getByRole('checkbox', { name: '❯Mark all as complete' }).click(); - - // Verify "Mark all as complete" checkbox is checked - await expect(page.getByRole('checkbox', { name: '❯Mark all as complete' })).toBeChecked(); - - // Verify counter shows "0 items left" - await expect(page.getByText('0')).toBeVisible(); - - // Verify "Clear completed" button appears - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/completing-todos/uncomplete-todo.spec.ts b/examples/todomvc/tests/completing-todos/uncomplete-todo.spec.ts deleted file mode 100644 index 9b26a22cdf75a..0000000000000 --- a/examples/todomvc/tests/completing-todos/uncomplete-todo.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -// spec: Completing Todos - should uncomplete todo -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Completing Todos', () => { - test('should uncomplete todo', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the checkbox to complete it - await page.getByRole('checkbox', { name: 'Toggle Todo' }).click(); - - // Click the checkbox again to uncomplete it - await page.getByRole('checkbox', { name: 'Toggle Todo' }).click(); - - // Verify checkbox becomes unchecked - await expect(page.getByRole('checkbox', { name: 'Toggle Todo' })).not.toBeChecked(); - - // Verify counter shows "1 item left" - await expect(page.getByText('1 item left')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/completing-todos/unmark-all-as-complete.spec.ts b/examples/todomvc/tests/completing-todos/unmark-all-as-complete.spec.ts deleted file mode 100644 index afff06aebe2f2..0000000000000 --- a/examples/todomvc/tests/completing-todos/unmark-all-as-complete.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -// spec: Completing Todos - should unmark all as complete -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Completing Todos', () => { - test('should unmark all as complete', async ({ page }) => { - // Add first todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add second todo: "Walk the dog" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Walk the dog'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Add third todo: "Read a book" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Read a book'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the "Mark all as complete" checkbox to complete all - await page.getByRole('checkbox', { name: '❯Mark all as complete' }).click(); - - // Click the "Mark all as complete" checkbox again - await page.getByRole('checkbox', { name: '❯Mark all as complete' }).click(); - - // Verify "Mark all as complete" checkbox is unchecked - await expect(page.getByRole('checkbox', { name: '❯Mark all as complete' })).not.toBeChecked(); - - // Verify all individual checkboxes are unchecked - await expect(page.getByRole('listitem').filter({ hasText: 'Buy groceries' }).getByLabel('Toggle Todo')).not.toBeChecked(); - await expect(page.getByRole('listitem').filter({ hasText: 'Walk the dog' }).getByLabel('Toggle Todo')).not.toBeChecked(); - await expect(page.getByRole('listitem').filter({ hasText: 'Read a book' }).getByLabel('Toggle Todo')).not.toBeChecked(); - - // Verify counter shows "3 items left" - await expect(page.getByText('3 items left')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/editing-todos/cancel-edit-with-escape.spec.ts b/examples/todomvc/tests/editing-todos/cancel-edit-with-escape.spec.ts deleted file mode 100644 index 9a7d57f07c50d..0000000000000 --- a/examples/todomvc/tests/editing-todos/cancel-edit-with-escape.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -// spec: Editing Todos - Cancel edit with escape -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Editing Todos', () => { - test('should cancel edit with escape', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Double-click on the todo text - await page.getByTestId('todo-title').dblclick(); - - // Type "Changed text" - await page.getByRole('textbox', { name: 'Edit' }).fill('Changed text'); - - // Press Escape key - await page.keyboard.press('Escape'); - - // Verify original text "Buy groceries" is preserved - await expect(page.getByText('Buy groceries')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/editing-todos/delete-todo-by-clearing-text.spec.ts b/examples/todomvc/tests/editing-todos/delete-todo-by-clearing-text.spec.ts deleted file mode 100644 index 312002502d685..0000000000000 --- a/examples/todomvc/tests/editing-todos/delete-todo-by-clearing-text.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -// spec: Editing Todos - should delete todo by clearing text -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Editing Todos', () => { - test('should delete todo by clearing text', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Double-click on the todo text - await page.getByTestId('todo-title').dblclick(); - - // Clear all text (delete all characters) - await page.getByRole('textbox', { name: 'Edit' }).fill(''); - - // Press Enter - await page.keyboard.press('Enter'); - - // Verify the input field is still visible - await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/editing-todos/edit-completed-todo.spec.ts b/examples/todomvc/tests/editing-todos/edit-completed-todo.spec.ts deleted file mode 100644 index 20d79b95d6e54..0000000000000 --- a/examples/todomvc/tests/editing-todos/edit-completed-todo.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -// spec: Editing Todos - Edit Completed Todo -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Editing Todos', () => { - test('should edit completed todo', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Click the checkbox to complete it - await page.getByRole('checkbox', { name: 'Toggle Todo' }).click(); - - // Double-click on the todo text - await page.getByTestId('todo-title').dblclick(); - - // Type "Buy groceries and milk" and press Enter - await page.getByRole('textbox', { name: 'Edit' }).fill('Buy groceries and milk'); - await page.getByRole('textbox', { name: 'Edit' }).press('Enter'); - - // Verify todo text is successfully updated - await expect(page.getByText('Buy groceries and milk')).toBeVisible(); - - // Verify checkbox remains checked (todo remains in completed state) - await expect(page.getByRole('checkbox', { name: 'Toggle Todo' })).toBeChecked(); - }); -}); diff --git a/examples/todomvc/tests/editing-todos/edit-todo-successfully.spec.ts b/examples/todomvc/tests/editing-todos/edit-todo-successfully.spec.ts deleted file mode 100644 index a9e9fcbfe03f9..0000000000000 --- a/examples/todomvc/tests/editing-todos/edit-todo-successfully.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -// spec: Editing Todos - should edit todo successfully -// seed: tests/seed.spec.ts - -import { test, expect } from '../fixtures'; - -test.describe('Editing Todos', () => { - test('should edit todo successfully', async ({ page }) => { - // Add a todo: "Buy groceries" - await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); - await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); - - // Double-click on the todo text "Buy groceries" - await page.getByTestId('todo-title').dblclick(); - - // Clear the existing text and type "Buy groceries and milk" - await page.getByRole('textbox', { name: 'Edit' }).fill('Buy groceries and milk'); - - // Press Enter to save the edited todo - await page.keyboard.press('Enter'); - - // Verify that todo text updates to "Buy groceries and milk" - await expect(page.getByText('Buy groceries and milk')).toBeVisible(); - }); -}); diff --git a/examples/todomvc/tests/todo-creation/add-multiple-todos.spec.ts b/examples/todomvc/tests/todo-creation/add-multiple-todos.spec.ts new file mode 100644 index 0000000000000..37c035a240342 --- /dev/null +++ b/examples/todomvc/tests/todo-creation/add-multiple-todos.spec.ts @@ -0,0 +1,41 @@ +// seed: tests/seed.spec.ts + +import { test, expect } from '../fixtures'; + +test.describe('Todo Creation', () => { + test('Add multiple todos', async ({ page }) => { + // 1. Navigate to the TodoMVC application + // Expect: The page loads with an empty todo list + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); + + // 2. Add first todo 'Buy groceries' by typing and pressing Enter + const newTodoInput = page.getByRole('textbox', { name: 'What needs to be done?' }); + await newTodoInput.fill('Buy groceries'); + await newTodoInput.press('Enter'); + // Expect: The first todo appears in the list + await expect(page.getByText('Buy groceries')).toBeVisible(); + + // 3. Add second todo 'Walk the dog' by typing and pressing Enter + await newTodoInput.fill('Walk the dog'); + await newTodoInput.press('Enter'); + // Expect: The second todo appears in the list below the first + await expect(page.getByText('Walk the dog')).toBeVisible(); + + // 4. Add third todo 'Read a book' by typing and pressing Enter + await newTodoInput.fill('Read a book'); + await newTodoInput.press('Enter'); + // Expect: The third todo appears in the list below the second + await expect(page.getByText('Read a book')).toBeVisible(); + + // Post Conditions: All three todos are visible in the list + await expect(page.getByText('Buy groceries')).toBeVisible(); + await expect(page.getByText('Walk the dog')).toBeVisible(); + await expect(page.getByText('Read a book')).toBeVisible(); + + // Post Conditions: The todo counter shows '3 items left' + await expect(page.getByText('3 items left')).toBeVisible(); + + // Post Conditions: All todos are in active (unchecked) state + await expect(page.getByRole('listitem').filter({ hasText: 'Buy groceries' }).getByLabel('Toggle Todo')).not.toBeChecked(); + }); +}); diff --git a/examples/todomvc/tests/todo-creation/add-single-todo.spec.ts b/examples/todomvc/tests/todo-creation/add-single-todo.spec.ts new file mode 100644 index 0000000000000..1b193c70db0ad --- /dev/null +++ b/examples/todomvc/tests/todo-creation/add-single-todo.spec.ts @@ -0,0 +1,32 @@ +// seed: tests/seed.spec.ts + +import { test, expect } from '../fixtures'; + +test.describe('Todo Creation', () => { + test('Add a single todo', async ({ page }) => { + // 1. Navigate to the TodoMVC application + // Expect: The page loads with an empty todo list and input field 'What needs to be done?' is visible + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); + + // 2. Type 'Buy groceries' into the input field + await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy groceries'); + + // Expect: The text appears in the input field + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue('Buy groceries'); + + // 3. Press Enter to submit the todo + await page.keyboard.press('Enter'); + + // Expect: The todo 'Buy groceries' appears in the list + await expect(page.getByText('Buy groceries')).toBeVisible(); + + // Expect: The input field is cleared + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue(''); + + // Post Condition - The todo counter shows '1 item left' + await expect(page.getByText('1 item left')).toBeVisible(); + + // Post Condition - The new todo is unchecked (active state) + await expect(page.getByRole('checkbox', { name: 'Toggle Todo' })).not.toBeChecked(); + }); +}); diff --git a/examples/todomvc/tests/todo-creation/add-todo-special-chars.spec.ts b/examples/todomvc/tests/todo-creation/add-todo-special-chars.spec.ts new file mode 100644 index 0000000000000..ae05e3c644868 --- /dev/null +++ b/examples/todomvc/tests/todo-creation/add-todo-special-chars.spec.ts @@ -0,0 +1,21 @@ +// seed: tests/seed.spec.ts + +import { test, expect } from '../fixtures'; + +test.describe('Todo Creation', () => { + test('Add todo with special characters', async ({ page }) => { + // 1. Navigate to the TodoMVC application + // Expect: The page loads with an empty todo list + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); + + // 2. Type 'Buy @groceries & supplies (urgent!)' into the input field and press Enter + await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('Buy @groceries & supplies (urgent!)'); + await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); + + // Expect: The todo appears in the list with all special characters preserved + await expect(page.getByText('Buy @groceries & supplies (urgent!)')).toBeVisible(); + + // Post Condition: The todo counter shows '1 item left' + await expect(page.getByText('1 item left')).toBeVisible(); + }); +}); diff --git a/examples/todomvc/tests/todo-creation/prevent-empty-todo.spec.ts b/examples/todomvc/tests/todo-creation/prevent-empty-todo.spec.ts new file mode 100644 index 0000000000000..eb6bfcf624187 --- /dev/null +++ b/examples/todomvc/tests/todo-creation/prevent-empty-todo.spec.ts @@ -0,0 +1,23 @@ +// spec: Todo Creation - Prevent adding empty todo +// seed: tests/seed.spec.ts + +import { test, expect } from '../fixtures'; + +test.describe('Todo Creation', () => { + test('Prevent adding empty todo', async ({ page }) => { + // Step 1: Navigate to the TodoMVC application + // Expect: The page loads with an empty todo list + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); + + // Step 2: Click into the input field without typing anything and press Enter + // Expect: No todo is added to the list + await page.getByRole('textbox', { name: 'What needs to be done?' }).click(); + await page.keyboard.press('Enter'); + + // Post Conditions: The todo list remains empty + await expect(page.locator('.todo-list li')).toHaveCount(0); + + // Post Conditions: The input field is still focused and empty + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toHaveValue(''); + }); +}); diff --git a/examples/todomvc/tests/todo-creation/prevent-whitespace-todo.spec.ts b/examples/todomvc/tests/todo-creation/prevent-whitespace-todo.spec.ts new file mode 100644 index 0000000000000..80f6c5e69bbc8 --- /dev/null +++ b/examples/todomvc/tests/todo-creation/prevent-whitespace-todo.spec.ts @@ -0,0 +1,20 @@ +// spec: Todo Creation - Prevent adding whitespace-only todo +// seed: tests/seed.spec.ts + +import { test, expect } from '../fixtures'; + +test.describe('Todo Creation', () => { + test('Prevent adding whitespace-only todo', async ({ page }) => { + // 1. Navigate to the TodoMVC application + // Expect: The page loads with an empty todo list + await expect(page.getByRole('textbox', { name: 'What needs to be done?' })).toBeVisible(); + + // 2. Type only spaces ' ' into the input field and press Enter + // Expect: No todo is added to the list + await page.getByRole('textbox', { name: 'What needs to be done?' }).fill(' '); + await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter'); + + // Verify no todo was added (todo list remains empty) + await expect(page.getByRole('listitem')).toHaveCount(0); + }); +}); diff --git a/packages/playwright/src/mcp/test/plannerTools.ts b/packages/playwright/src/mcp/test/plannerTools.ts index 0778f1894dfe1..64afd376947ec 100644 --- a/packages/playwright/src/mcp/test/plannerTools.ts +++ b/packages/playwright/src/mcp/test/plannerTools.ts @@ -47,8 +47,11 @@ const planSchema = z.object({ tests: z.array(z.object({ name: z.string().describe('The name of the test'), file: z.string().describe('The file the test should be saved to, for example: "tests//.spec.ts".'), - steps: z.array(z.string().describe(`The steps to be executed to perform the test. For example: 'Click on the "Submit" button'`)), - expectedResults: z.array(z.string().describe('The expected results of the steps for test to verify.')), + steps: z.array(z.object({ + perform: z.string().describe(`Action to perform. For example: 'Click on the "Submit" button'.`), + expect: z.string().optional().describe(`Expected result of the action where appropriate. For example: 'The page should show the "Thank you for your submission" message'`), + })), + postConditions: z.array(z.string().describe(`Post conditions to verify that are not covered by the steps. Can be empty`)), })), })), }); @@ -107,12 +110,17 @@ export const saveTestPlan = defineTestTool({ lines.push(`**File:** \`${test.file}\``); lines.push(``); lines.push(`**Steps:**`); - for (let k = 0; k < test.steps.length; k++) - lines.push(` ${k + 1}. ${test.steps[k]}`); - lines.push(``); - lines.push(`**Expected Results:**`); - for (const result of test.expectedResults) - lines.push(` - ${result}`); + for (let k = 0; k < test.steps.length; k++) { + lines.push(` ${k + 1}. ${test.steps[k].perform}`); + if (test.steps[k].expect?.trim()) + lines.push(` ${' '.repeat(String(k + 1).length)} Expect: ${test.steps[k].expect}`); + } + if (test.postConditions.length) { + lines.push(``); + lines.push(`**Post Conditions:**`); + for (const postCondition of test.postConditions) + lines.push(` - ${postCondition}`); + } } } lines.push(``); From ec394723d0aa0c2af12bf374858c1603df562327 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 31 Dec 2025 11:49:18 -0800 Subject: [PATCH 2/2] Update plannerTools.ts Co-authored-by: Yury Semikhatsky Signed-off-by: Pavel Feldman --- packages/playwright/src/mcp/test/plannerTools.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright/src/mcp/test/plannerTools.ts b/packages/playwright/src/mcp/test/plannerTools.ts index 64afd376947ec..9e2dc90e895af 100644 --- a/packages/playwright/src/mcp/test/plannerTools.ts +++ b/packages/playwright/src/mcp/test/plannerTools.ts @@ -113,7 +113,7 @@ export const saveTestPlan = defineTestTool({ for (let k = 0; k < test.steps.length; k++) { lines.push(` ${k + 1}. ${test.steps[k].perform}`); if (test.steps[k].expect?.trim()) - lines.push(` ${' '.repeat(String(k + 1).length)} Expect: ${test.steps[k].expect}`); + lines.push(` ${' '.repeat(String(k + 1).length)} Expect: ${test.steps[k].expect}`); } if (test.postConditions.length) { lines.push(``);