diff --git a/packages/playwright/src/agents/playwright-test-planner.agent.md b/packages/playwright/src/agents/playwright-test-planner.agent.md
index f74ccfdccd2a6..ce0780ba569ef 100644
--- a/packages/playwright/src/agents/playwright-test-planner.agent.md
+++ b/packages/playwright/src/agents/playwright-test-planner.agent.md
@@ -5,7 +5,6 @@ model: sonnet
color: green
tools:
- search
- - edit
- playwright-test/browser_click
- playwright-test/browser_close
- playwright-test/browser_console_messages
@@ -24,6 +23,7 @@ tools:
- playwright-test/browser_type
- playwright-test/browser_wait_for
- playwright-test/planner_setup_page
+ - playwright-test/planner_save_plan
---
You are an expert web test planner with extensive experience in quality assurance, user experience testing, and test
@@ -61,52 +61,7 @@ You will:
5. **Create Documentation**
- Save your test plan as requested:
- - Executive summary of the tested page/application
- - Individual scenarios as separate sections
- - Each scenario formatted with numbered steps
- - Each test case with proposed file name for implementation
- - Clear expected results for verification
-
-
-# TodoMVC Application - Comprehensive Test Plan
-
-## Application Overview
-
-The TodoMVC application is a React-based todo list manager that provides core task management functionality. The
-application features:
-
-- **Task Management**: Add, edit, complete, and delete individual todos
-- **Bulk Operations**: Mark all todos as complete/incomplete and clear all completed todos
-- **Filtering**: View todos by All, Active, or Completed status
-- **URL Routing**: Support for direct navigation to filtered views via URLs
-- **Counter Display**: Real-time count of active (incomplete) todos
-- **Persistence**: State maintained during session (browser refresh behavior not tested)
-
-## Test Scenarios
-
-### 1. Adding New Todos
-
-**Seed:** `tests/seed.spec.ts`
-
-#### 1.1 Add Valid Todo
-
-**File** `tests/adding-new-todos/add-valid-todo.spec.ts`
-
-**Steps:**
-1. Click in the "What needs to be done?" input field
-2. Type "Buy groceries"
-3. Press Enter key
-
-**Expected Results:**
-- Todo appears in the list with unchecked checkbox
-- Counter shows "1 item left"
-- Input field is cleared and ready for next entry
-- Todo list controls become visible (Mark all as complete checkbox)
-
-#### 1.2
-...
-
+ Submit your test plan using `planner_save_plan` tool.
**Quality Standards**:
- Write steps that are specific enough for any tester to follow
diff --git a/packages/playwright/src/mcp/test/plannerTools.ts b/packages/playwright/src/mcp/test/plannerTools.ts
index 02ef964151795..e405adc9aa82f 100644
--- a/packages/playwright/src/mcp/test/plannerTools.ts
+++ b/packages/playwright/src/mcp/test/plannerTools.ts
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+import fs from 'fs';
+import path from 'path';
+
import { z } from '../sdk/bundle';
import { defineTestTool } from './testTool';
@@ -35,3 +38,90 @@ export const setupPage = defineTestTool({
return { content: [] };
},
});
+
+const planSchema = z.object({
+ overview: z.string().describe('A brief overview of the application to be tested'),
+ suites: z.array(z.object({
+ name: z.string().describe('The name of the suite'),
+ seedFile: z.string().describe('A seed file that was used to setup the page for testing.'),
+ 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.')),
+ })),
+ })),
+});
+
+export const submitTestPlan = defineTestTool({
+ schema: {
+ name: 'planner_submit_plan',
+ title: 'Submit test plan',
+ description: 'Submit the test plan to the test planner',
+ inputSchema: planSchema,
+ type: 'readOnly',
+ },
+
+ handle: async (context, params) => {
+ return {
+ content: [{
+ type: 'text',
+ text: JSON.stringify(params, null, 2),
+ }],
+ };
+ },
+});
+
+export const saveTestPlan = defineTestTool({
+ schema: {
+ name: 'planner_save_plan',
+ title: 'Save test plan as markdown file',
+ description: 'Save the test plan as a markdown file',
+ inputSchema: planSchema.extend({
+ name: z.string().describe('The name of the test plan, for example: "Test Plan".'),
+ fileName: z.string().describe('The file to save the test plan to, for example: "spec/test.plan.md". Relative to the workspace root.'),
+ }),
+ type: 'readOnly',
+ },
+
+ handle: async (context, params) => {
+ const lines: string[] = [];
+ lines.push(`# ${params.name}`);
+ lines.push(``);
+ lines.push(`## Application Overview`);
+ lines.push(``);
+ lines.push(params.overview);
+ lines.push(``);
+ lines.push(`## Test Scenarios`);
+ for (let i = 0; i < params.suites.length; i++) {
+ lines.push(``);
+ const suite = params.suites[i];
+ lines.push(`### ${i + 1}. ${suite.name}`);
+ lines.push(``);
+ lines.push(`**Seed:** \`${suite.seedFile}\``);
+ for (let j = 0; j < suite.tests.length; j++) {
+ lines.push(``);
+ const test = suite.tests[j];
+ lines.push(`#### ${i + 1}.${j + 1}. ${test.name}`);
+ lines.push(``);
+ 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}`);
+ }
+ }
+ lines.push(``);
+ await fs.promises.writeFile(path.resolve(context.rootPath, params.fileName), lines.join('\n'));
+ return {
+ content: [{
+ type: 'text',
+ text: `Test plan saved to ${params.fileName}`,
+ }],
+ };
+ },
+});