chrometools-mcp 3.3.8 → 3.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [3.3.9] - 2026-02-08
6
+
7
+ ### Added
8
+ - **AI Hints: modal content extraction** — Modals now show title, body text (200 chars), and action buttons
9
+ - Expanded selectors: mat-dialog-container, cdk-overlay-pane, `[class*="dialog"]`
10
+ - Topmost modal dedup for pages with multiple modals
11
+ - Actions extracted from `.modal-footer` / `[mat-dialog-actions]` (limit 5)
12
+
13
+ - **AI Hints: dropdown/menu item extraction** — Overlays now list actual option texts
14
+ - 11 overlay selectors: Angular CDK/Material, PrimeNG, Ant Design, custom `select-options`
15
+ - Menu vs dropdown auto-classification (role="menu", role="listbox", menuitem detection)
16
+ - Item text extraction (limit 10 items, shows total count)
17
+ - Deduplication of nested overlay elements
18
+
19
+ - **AI Hints: page heading in navigation** — `navigateTo` and `openBrowser` now show page heading
20
+ - Extracts h1 or `.page-title` / `[class*="page-title"]` fallback for SPAs
21
+ - Filters sr-only/visually-hidden elements (clip, 1px size, opacity)
22
+ - 500ms SPA render delay for Angular/React/Vue frameworks
23
+
24
+ - **Swagger/OpenAPI tools** — `loadSwagger` and `generateApiModels` (Phase 1)
25
+ - `loadSwagger`: Parse OpenAPI 2.0/3.x specs from URL or file (JSON/YAML)
26
+ - `generateApiModels`: Generate TypeScript interfaces or Python models (dataclass/pydantic/TypedDict)
27
+ - $ref resolution, enum generation, snake_case conversion for Python
28
+ - Supports filtering specific schemas
29
+
30
+ - **Page Object Model integration in exported tests** — `pageObjectMode` parameter
31
+ - `generate-integrated`: Generate POM + test using it
32
+ - `use-existing`: Generate test referencing existing POM file
33
+ - Works with `exportScenarioAsCode` and `appendScenarioToFile`
34
+
35
+ - **Synthetic drag mode** — `drag` tool now supports `mode: 'synthetic'`
36
+ - Better compatibility with JS libraries (frappe-gantt, jQuery UI, Sortable.js)
37
+ - Native mode (default) for standard HTML drag operations
38
+
39
+ - **analyzePage: framework click handler detection** — Detect addEventListener-based handlers
40
+ - APOM IDs returned from `smartFindElement` and `findElementsByText`
41
+
42
+ ### Fixed
43
+ - Swagger Phase 1 code review fixes (error handling, edge cases)
44
+
5
45
  ## [3.3.8] - 2026-02-03
6
46
 
7
47
  ### Added
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ## Why ChromeTools MCP?
8
8
 
9
9
  **For AI Agents & Developers:**
10
- - 🎯 **54 specialized tools** for browser automation - from simple clicks to Figma comparisons
10
+ - 🎯 **56 specialized tools** for browser automation - from simple clicks to Figma comparisons
11
11
  - 🧠 **APOM (Agent Page Object Model)** - AI-friendly page representation (~8-10k tokens vs 15-25k for screenshots)
12
12
  - 🔄 **Persistent browser sessions** - pages stay open between commands for iterative workflows
13
13
  - ⚡ **Framework-aware** - handles React, Vue, Angular events and state updates automatically
@@ -219,7 +219,7 @@ The Chrome Extension is **required** for scenario recording and other advanced f
219
219
  - [Installation](#installation)
220
220
  - [Chrome Extension Setup](#chrome-extension-setup)
221
221
  - [AI Optimization Features](#ai-optimization-features)- [Scenario Recorder](#scenario-recorder) - Visual UI-based recording with smart optimization
222
- - [Available Tools](#available-tools) - **46+ Tools Total**
222
+ - [Available Tools](#available-tools) - **48+ Tools Total**
223
223
  - [AI-Powered Tools](#ai-powered-tools) - smartFindElement, analyzePage, getElementDetails, findElementsByText
224
224
  - [Core Tools](#1-core-tools) - ping, openBrowser
225
225
  - [Interaction Tools](#2-interaction-tools) - click, type, scrollTo, selectOption, selectFromGroup, drag, scrollHorizontal
@@ -227,6 +227,7 @@ The Chrome Extension is **required** for scenario recording and other advanced f
227
227
  - [Advanced Tools](#4-advanced-tools) - executeScript, getConsoleLogs, listNetworkRequests, getNetworkRequest, filterNetworkRequests, hover, setStyles, setViewport, getViewport, navigateTo
228
228
  - [Tab Management Tools](#5-tab-management-tools) - listTabs, switchTab
229
229
  - [Recorder Tools](#7-recorder-tools) - enableRecorder, executeScenario, listScenarios, searchScenarios, getScenarioInfo, deleteScenario, exportScenarioAsCode, appendScenarioToFile, generatePageObject
230
+ - [API / Swagger Tools](#8-api--swagger-tools) - loadSwagger, generateApiModels
230
231
  - [Typical Workflow Example](#typical-workflow-example)
231
232
  - [Tool Usage Tips](#tool-usage-tips)
232
233
  - [Configuration](#configuration)
@@ -260,7 +261,7 @@ AI: smartFindElement("login button")
260
261
 
261
262
  1. **`analyzePage`** - 🔥 **USE FREQUENTLY** - Get current page state after loads, clicks, submissions (cached, use refresh:true)
262
263
  2. **`smartFindElement`** - Natural language element search with multilingual support
263
- 3. **AI Hints** - Automatic context in all tools (page type, available actions, suggestions)
264
+ 3. **AI Hints** - Automatic context in all tools (page type, page heading, modal content, dropdown/menu items, suggestions)
264
265
  4. **Text search** - `findElementsByText` for finding elements by visible text
265
266
 
266
267
  **Performance:** 3-5x faster, 5-10x fewer requests
@@ -603,10 +604,16 @@ Drag element by mouse (click-hold-move-release). Simulates real mouse drag, not
603
604
  - `direction` (required): 'up', 'down', 'left', 'right', 'up-left', 'up-right', 'down-left', 'down-right'
604
605
  - `distance` (optional): Distance in pixels (default: 100)
605
606
  - `duration` (optional): Drag duration in milliseconds (default: 500)
607
+ - `mode` (optional): 'native' (default) or 'synthetic'
608
+ - **'native'**: Uses Puppeteer mouse API - faster, works for most cases
609
+ - **'synthetic'**: Dispatches DOM events (pointerdown/pointermove/pointerup) - better compatibility with JS libraries (frappe-gantt, jQuery UI Draggable, custom drag handlers)
606
610
  - **Use case**: Interactive maps (Google Maps, Leaflet), Gantt charts, SVG diagrams, canvas elements, sliders, drag-to-pan interfaces
607
- - **How it works**: Moves mouse to element center, presses mouse button, drags to target position, releases button
611
+ - **How it works**:
612
+ - **Native mode**: Uses Puppeteer's mouse API (mousedown → mousemove → mouseup)
613
+ - **Synthetic mode**: Dispatches PointerEvent/MouseEvent on element with intermediate pointermove events during drag
614
+ - **When to use synthetic mode**: If native drag doesn't trigger JS library event handlers (e.g., frappe-gantt, jQuery UI, React DnD)
608
615
  - **NOT for**: Standard overflow scrollbars (use `scrollTo` or `scrollHorizontal` instead)
609
- - **Returns**: Start/end mouse positions and drag delta
616
+ - **Returns**: Start/end mouse positions, drag delta, and mode used
610
617
 
611
618
  #### scrollHorizontal
612
619
  Scroll element horizontally (for tables, carousels, wide content).
@@ -1118,17 +1125,24 @@ Delete a scenario and its associated secrets. Searches all projects to find the
1118
1125
  - `language` (required): Target framework - `"playwright-typescript"`, `"playwright-python"`, `"selenium-python"`, `"selenium-java"`
1119
1126
  - `cleanSelectors` (optional): Remove unstable CSS classes (default: true)
1120
1127
  - `includeComments` (optional): Include descriptive comments (default: true)
1121
- - `generatePageObject` (optional): Also generate Page Object class for the page (default: false)
1128
+ - `generatePageObject` (optional): Also generate Page Object class for the page (default: false). Legacy - use `pageObjectMode` instead.
1122
1129
  - `pageObjectClassName` (optional): Custom Page Object class name (auto-generated if not provided)
1130
+ - `pageObjectMode` (optional): POM integration mode:
1131
+ - `"none"` (default) - no Page Object
1132
+ - `"generate"` - generate separate POM file (same as `generatePageObject: true`)
1133
+ - `"generate-integrated"` - generate POM + test that **uses** POM methods (imports, instantiates, calls POM methods)
1134
+ - `"use-existing"` - generate test that uses an **existing** POM file (requires `pageObjectFile`)
1135
+ - `pageObjectFile` (optional): Path to existing POM file (required for `"use-existing"` mode)
1123
1136
 
1124
- - **Use case**: Create new test files from recorded scenarios with optional Page Objects
1137
+ - **Use case**: Create new test files from recorded scenarios with optional Page Object integration
1125
1138
 
1126
1139
  - **Returns**: JSON with:
1127
1140
  - `action`: `"create_new_file"`
1128
1141
  - `suggestedFileName`: Suggested test filename
1129
1142
  - `testCode`: Full test code with imports
1130
1143
  - `instruction`: Instructions for Claude Code
1131
- - `pageObject` (if `generatePageObject=true`): Page Object code and metadata
1144
+ - `pageObject` (if POM generated): Page Object code and metadata
1145
+ - `pomIntegration` (if POM integrated): `{ className, mode }` info
1132
1146
 
1133
1147
  - **Example 1 - Test only**:
1134
1148
  ```javascript
@@ -1147,29 +1161,46 @@ Delete a scenario and its associated secrets. Searches all projects to find the
1147
1161
  }
1148
1162
  ```
1149
1163
 
1150
- - **Example 2 - Test + Page Object**:
1164
+ - **Example 2 - Test + separate Page Object** (legacy):
1151
1165
  ```javascript
1152
- // Export with Page Object class
1153
1166
  exportScenarioAsCode({
1154
1167
  scenarioName: "login_test",
1155
1168
  language: "playwright-typescript",
1156
1169
  generatePageObject: true,
1157
1170
  pageObjectClassName: "LoginPage"
1158
1171
  })
1172
+ ```
1159
1173
 
1160
- // Returns JSON with both files:
1161
- {
1162
- "action": "create_new_file",
1163
- "suggestedFileName": "login_test.spec.ts",
1164
- "testCode": "import { test } from '@playwright/test';\nimport { LoginPage } from './LoginPage';\n\ntest('login_test', async ({ page }) => {\n const loginPage = new LoginPage(page);\n await loginPage.goto();\n await loginPage.fillEmailInput('user@test.com');\n await loginPage.clickLoginButton();\n});",
1165
- "pageObject": {
1166
- "code": "import { Page, Locator } from '@playwright/test';\n\nexport class LoginPage { ... }",
1167
- "className": "LoginPage",
1168
- "suggestedFileName": "LoginPage.ts",
1169
- "elementCount": 12
1170
- },
1171
- "instruction": "Create a new test file 'login_test.spec.ts' with the testCode. Also create a Page Object file 'LoginPage.ts' with the pageObject.code."
1172
- }
1174
+ - **Example 3 - Test + integrated Page Object** (recommended):
1175
+ ```javascript
1176
+ // Generate POM and test that USES POM methods (not raw selectors)
1177
+ exportScenarioAsCode({
1178
+ scenarioName: "login_test",
1179
+ language: "playwright-typescript",
1180
+ pageObjectMode: "generate-integrated",
1181
+ pageObjectClassName: "LoginPage"
1182
+ })
1183
+
1184
+ // Returns test code using POM:
1185
+ // import { LoginPage } from './LoginPage';
1186
+ // test('login_test', async ({ page }) => {
1187
+ // const loginPage = new LoginPage(page);
1188
+ // await loginPage.goto();
1189
+ // await loginPage.fillUsername('admin');
1190
+ // await loginPage.clickLoginBtn();
1191
+ // });
1192
+ ```
1193
+
1194
+ - **Example 4 - Test using existing POM file**:
1195
+ ```javascript
1196
+ // Use pre-existing Page Object file
1197
+ exportScenarioAsCode({
1198
+ scenarioName: "login_test",
1199
+ language: "playwright-typescript",
1200
+ pageObjectMode: "use-existing",
1201
+ pageObjectFile: "./pages/LoginPage.ts"
1202
+ })
1203
+ // Test will import and use methods from the existing LoginPage
1173
1204
  ```
1174
1205
 
1175
1206
  - **Selector Cleaning**: Automatically removes unstable patterns:
@@ -1191,8 +1222,10 @@ Append recorded scenario as test code to an **EXISTING** test file. Automaticall
1191
1222
  - `referenceTestName` (optional): Reference test name for 'before'/'after' insertion
1192
1223
  - `cleanSelectors` (optional): Remove unstable CSS classes (default: true)
1193
1224
  - `includeComments` (optional): Include descriptive comments (default: true)
1194
- - `generatePageObject` (optional): Also generate Page Object class for the page (default: false)
1225
+ - `generatePageObject` (optional): Also generate Page Object class for the page (default: false). Legacy - use `pageObjectMode` instead.
1195
1226
  - `pageObjectClassName` (optional): Custom Page Object class name (auto-generated if not provided)
1227
+ - `pageObjectMode` (optional): POM integration mode - `"none"`, `"generate"`, `"generate-integrated"`, `"use-existing"` (see exportScenarioAsCode for details)
1228
+ - `pageObjectFile` (optional): Path to existing POM file (required for `"use-existing"` mode)
1196
1229
 
1197
1230
  - **Use case**: Add tests to existing test files without overwriting current tests
1198
1231
 
@@ -1325,6 +1358,78 @@ Append recorded scenario as test code to an **EXISTING** test file. Automaticall
1325
1358
  - `selenium-python`: Selenium with Python (WebDriver, explicit waits, By locators)
1326
1359
  - `selenium-java`: Selenium with Java (WebDriver, Page Factory compatible)
1327
1360
 
1361
+ ### 8. API / Swagger Tools
1362
+
1363
+ Tools for loading OpenAPI/Swagger specs and generating typed API models.
1364
+
1365
+ #### `loadSwagger`
1366
+
1367
+ Parse an OpenAPI 2.0 (Swagger) or 3.x spec and return a structured summary of endpoints, schemas, and auth.
1368
+
1369
+ | Parameter | Type | Required | Description |
1370
+ |-----------|------|----------|-------------|
1371
+ | `source` | string | Yes | URL (`https://...`) or local file path to `swagger.json` / `openapi.yaml` |
1372
+ | `format` | `'auto'` \| `'json'` \| `'yaml'` | No | Parse format (default: `auto` — detects from content) |
1373
+
1374
+ **Response includes:**
1375
+ - API title, version, base URL
1376
+ - All endpoints with method, path, operationId, parameters, request body, responses
1377
+ - Schema summaries (property names, types, enums)
1378
+ - Auth schemes (Bearer, API key, OAuth2)
1379
+
1380
+ ```javascript
1381
+ // Load from URL
1382
+ loadSwagger({ source: "https://petstore.swagger.io/v2/swagger.json" })
1383
+
1384
+ // Load from local file
1385
+ loadSwagger({ source: "/path/to/openapi.yaml" })
1386
+ ```
1387
+
1388
+ #### `generateApiModels`
1389
+
1390
+ Generate TypeScript interfaces or Python dataclasses/pydantic models from an OpenAPI spec.
1391
+
1392
+ | Parameter | Type | Required | Description |
1393
+ |-----------|------|----------|-------------|
1394
+ | `source` | string | Yes | URL or file path to spec |
1395
+ | `language` | `'typescript'` \| `'python'` | Yes | Target language |
1396
+ | `format` | `'auto'` \| `'json'` \| `'yaml'` | No | Parse format (default: `auto`) |
1397
+ | `style` | `'interface'` \| `'type'` | No | TypeScript style (default: `interface`) |
1398
+ | `pythonStyle` | `'dataclass'` \| `'pydantic'` \| `'typeddict'` | No | Python style (default: `dataclass`) |
1399
+ | `includeEnums` | boolean | No | Generate enum types (default: `true`) |
1400
+ | `schemas` | string[] | No | Filter to specific schema names |
1401
+
1402
+ **Features:**
1403
+ - Topological sort ensures correct declaration order
1404
+ - Enum deduplication (property enums reuse top-level enums)
1405
+ - `allOf` → extends/inheritance, `oneOf`/`anyOf` → union types
1406
+ - Circular reference detection with forward references
1407
+ - Swagger 2.0 automatically normalized to OpenAPI 3.x
1408
+
1409
+ ```javascript
1410
+ // Generate TypeScript interfaces
1411
+ generateApiModels({
1412
+ source: "https://petstore.swagger.io/v2/swagger.json",
1413
+ language: "typescript"
1414
+ })
1415
+ // Returns: { code: "export interface Pet { ... }", suggestedFileName: "pet-store-api.models.ts" }
1416
+
1417
+ // Generate Python pydantic models
1418
+ generateApiModels({
1419
+ source: "/path/to/openapi.yaml",
1420
+ language: "python",
1421
+ pythonStyle: "pydantic"
1422
+ })
1423
+ // Returns: { code: "class Pet(BaseModel): ...", suggestedFileName: "pet_store_api_models.py" }
1424
+
1425
+ // Generate only specific schemas
1426
+ generateApiModels({
1427
+ source: "https://api.example.com/openapi.json",
1428
+ language: "typescript",
1429
+ schemas: ["User", "Order"]
1430
+ })
1431
+ ```
1432
+
1328
1433
  ---
1329
1434
 
1330
1435
  ## Typical Workflow Example
@@ -0,0 +1,227 @@
1
+ # Спецификация: Интеграция Page Object Model в экспортируемые тесты
2
+
3
+ ## Контекст
4
+
5
+ QA-автоматизаторы жалуются, что тесты, экспортируемые через `exportScenarioAsCode` / `appendScenarioToFile`, **не используют Page Object**. Даже при `generatePageObject: true` генерируются два несвязанных файла — тест с raw-селекторами и POM-класс отдельно.
6
+
7
+ **Сейчас** (raw-селекторы):
8
+ ```typescript
9
+ test('login', async ({ page }) => {
10
+ await page.goto('https://example.com/login');
11
+ await page.locator('#username').fill('admin');
12
+ await page.locator('#password').fill('secret');
13
+ await page.locator('#login-btn').click();
14
+ });
15
+ ```
16
+
17
+ **Нужно** (POM-интеграция):
18
+ ```typescript
19
+ import { LoginPage } from './LoginPage';
20
+
21
+ test('login', async ({ page }) => {
22
+ const loginPage = new LoginPage(page);
23
+ await loginPage.goto();
24
+ await loginPage.fillUsername('admin');
25
+ await loginPage.fillPassword('secret');
26
+ await loginPage.clickLoginBtn();
27
+ });
28
+ ```
29
+
30
+ ## Подход
31
+
32
+ Добавить новый параметр `pageObjectMode` к тулам экспорта. Два сценария:
33
+
34
+ 1. **`generate-integrated`** — сгенерировать POM + тест, который его использует
35
+ 2. **`use-existing`** — прочитать существующий POM-файл, сгенерировать тест, который его использует
36
+
37
+ Ключевой механизм — **selector matching**: сопоставление селекторов из записанного сценария с локаторами POM-элементов.
38
+
39
+ ## Изменения по файлам
40
+
41
+ ### 1. Новый файл: `utils/code-generators/pom-integrator.js`
42
+
43
+ Модуль связки POM с экшнами сценария:
44
+
45
+ - **`matchActionToPomElement(actionSelector, pomElements)`** — сопоставляет селектор экшна с элементом POM:
46
+ 1. Exact match (`#username` === `#username`)
47
+ 2. Normalized match (strip tag prefix: `input#username` → `#username`)
48
+ 3. Key-based match (извлечь id/name/data-testid и сравнить значения)
49
+ 4. Не найдено → null (fallback на raw-селектор)
50
+
51
+ - **`parsePomFile(fileContent, framework)`** — парсит существующий POM-файл regex'ами, возвращает `{ className, elements: [{name, selector, methodName, methodType}] }`:
52
+ - Playwright TS: ищет `this.X = page.locator('...')` и `async fillX(` / `async clickX(`
53
+ - Playwright Python: ищет `self.X = page.locator('...')` и `def fill_X(` / `def click_X(`
54
+ - Selenium Python: ищет `X = (By.CSS_SELECTOR, '...')` и `def fill_X(` / `def click_X(`
55
+ - Selenium Java: ищет `By X = By.cssSelector("...")` и `void fillX(` / `void clickX(`
56
+
57
+ ### 2. Изменить: `recorder/page-object-generator.js`
58
+
59
+ Добавить в return `generatePageObject()` поле **`elements`** — массив структурированных метаданных:
60
+ ```js
61
+ elements: uniqueElements.map(el => ({
62
+ name: sanitizeIdentifier(el.name, lang),
63
+ selector: el.selector,
64
+ tag: el.tag,
65
+ type: el.type,
66
+ methodName: generateMethodName(el, framework), // "fillUsername" / "clickSubmit"
67
+ methodType: getMethodType(el) // "fill" | "click" | "select"
68
+ }))
69
+ ```
70
+ Добавить вспомогательные функции `generateMethodName()` и `getMethodType()` (логика уже есть в `generateActionMethods()`, нужно её вынести).
71
+
72
+ ### 3. Изменить: `utils/code-generators/code-generator-base.js`
73
+
74
+ Добавить в конструктор опции `pomElements`, `pomClassName`, `pomImportPath`.
75
+
76
+ Добавить методы с дефолтными реализациями (no-op):
77
+ - `generatePomImports(className, importPath)` → `[]`
78
+ - `generatePomInstantiation(className)` → `[]`
79
+ - `generatePomAction(action, pomElement)` → `null` (значит fallback)
80
+
81
+ Модифицировать `generate()` и `generateTestOnly()`:
82
+ ```js
83
+ // После generateImports(), если POM mode:
84
+ if (this.options.pomClassName) {
85
+ lines.push(...this.generatePomImports(this.options.pomClassName, this.options.pomImportPath));
86
+ }
87
+
88
+ // После generateTestHeader(), если POM mode:
89
+ if (this.options.pomClassName) {
90
+ lines.push(...this.generatePomInstantiation(this.options.pomClassName));
91
+ }
92
+
93
+ // В цикле экшнов:
94
+ for (const action of scenario.chain) {
95
+ let actionCode = null;
96
+ if (this.options.pomElements) {
97
+ const match = matchActionToPomElement(this.prepareSelector(action), this.options.pomElements);
98
+ if (match) {
99
+ actionCode = this.generatePomAction(action, match);
100
+ }
101
+ }
102
+ if (!actionCode) {
103
+ actionCode = this.generateAction(action);
104
+ }
105
+ if (actionCode?.length > 0) lines.push(...actionCode);
106
+ }
107
+ ```
108
+
109
+ Специальная обработка `navigate` → если URL совпадает с POM entryUrl, заменить на `pomInstance.goto()`.
110
+
111
+ ### 4. Изменить: `playwright-typescript.js`
112
+
113
+ Реализовать 3 POM-метода:
114
+ ```js
115
+ generatePomImports(className, importPath) {
116
+ return [`import { ${className} } from '${importPath || './' + className}';`];
117
+ }
118
+
119
+ generatePomInstantiation(className) {
120
+ const varName = className.charAt(0).toLowerCase() + className.slice(1);
121
+ return [this.indent(`const ${varName} = new ${className}(page);`), ''];
122
+ }
123
+
124
+ generatePomAction(action, pomElement) {
125
+ const varName = this.options.pomClassName.charAt(0).toLowerCase() + this.options.pomClassName.slice(1);
126
+ // fill → await varName.fillUsername('text');
127
+ // click → await varName.clickSubmit();
128
+ // select → await varName.selectCountry('US');
129
+ // other → await varName.elementName.hover();
130
+ }
131
+ ```
132
+
133
+ ### 5. Изменить: `playwright-python.js`
134
+
135
+ ```python
136
+ # Import: from login_page import LoginPage
137
+ # Instantiation: login_page = LoginPage(page)
138
+ # Fill: login_page.fill_username('text')
139
+ # Click: login_page.click_submit()
140
+ ```
141
+
142
+ ### 6. Изменить: `selenium-python.js`
143
+
144
+ ```python
145
+ # Import: from login_page import LoginPage
146
+ # Instantiation: login_page = LoginPage(driver)
147
+ # Fill: login_page.fill_username('text')
148
+ # Click: login_page.click_submit()
149
+ ```
150
+
151
+ ### 7. Изменить: `selenium-java.js`
152
+
153
+ ```java
154
+ // Import: import pages.LoginPage;
155
+ // Instantiation: LoginPage loginPage = new LoginPage(driver);
156
+ // Fill: loginPage.fillUsername("text");
157
+ // Click: loginPage.clickSubmit();
158
+ ```
159
+
160
+ ### 8. Изменить: `server/tool-schemas.js`
161
+
162
+ Добавить к `ExportScenarioAsCodeSchema` и `AppendScenarioToFileSchema`:
163
+ ```js
164
+ pageObjectMode: z.enum(['none', 'generate', 'generate-integrated', 'use-existing']).optional()
165
+ .describe("POM integration: 'none' (default), 'generate' (separate POM, current behavior), 'generate-integrated' (POM + test using it), 'use-existing' (test uses existing POM file)"),
166
+ pageObjectFile: z.string().optional()
167
+ .describe("Path to existing POM file (for 'use-existing' mode)"),
168
+ ```
169
+
170
+ ### 9. Изменить: `server/tool-definitions.js`
171
+
172
+ Обновить описания тулов `exportScenarioAsCode` и `appendScenarioToFile` — добавить `pageObjectMode` и `pageObjectFile` в `inputSchema.properties`.
173
+
174
+ ### 10. Изменить: `index.js` (экспорт-хендлеры)
175
+
176
+ **`exportScenarioAsCode` (~строка 3321):**
177
+ - При `pageObjectMode === 'generate-integrated'`: сгенерировать POM, передать `pomElements`/`pomClassName` в генератор → получить тест с POM-вызовами
178
+ - При `pageObjectMode === 'use-existing'`: прочитать POM-файл через `FileAppender.readFile()`, распарсить через `parsePomFile()`, передать в генератор
179
+ - При `pageObjectMode === 'generate'` или `generatePageObject: true`: текущее поведение (обратная совместимость)
180
+
181
+ **`appendScenarioToFile` (~строка 3182):**
182
+ - Аналогичная логика для `generateTestOnly()`
183
+
184
+ ### 11. Обновить: `README.md`
185
+
186
+ Документировать `pageObjectMode` и `pageObjectFile` параметры для обеих тул.
187
+
188
+ ## Обратная совместимость
189
+
190
+ - `generatePageObject: true` (bool) — работает как раньше (maps to `pageObjectMode: 'generate'`)
191
+ - Новое поведение только при явном `pageObjectMode: 'generate-integrated'` или `'use-existing'`
192
+ - Fallback: если экшн не сматчился с POM-элементом — raw-селектор (как сейчас)
193
+
194
+ ## Алгоритм Selector Matching
195
+
196
+ | Action selector | POM selector | Результат |
197
+ |---|---|---|
198
+ | `#username` | `#username` | Exact match |
199
+ | `input#username` | `#username` | Normalized (strip tag) |
200
+ | `[name="email"]` | `[name="email"]` | Exact match |
201
+ | `input[name="email"]` | `[name="email"]` | Key match (name=email) |
202
+ | `.complex > path:nth(2)` | `#username` | No match → raw fallback |
203
+
204
+ ## Порядок реализации
205
+
206
+ 1. `page-object-generator.js` — добавить `elements` metadata + helper-функции
207
+ 2. `pom-integrator.js` — создать (matching + parsing)
208
+ 3. `code-generator-base.js` — POM-методы + модифицированный generate-цикл
209
+ 4. `playwright-typescript.js` — имплементация POM-методов (reference)
210
+ 5. `playwright-python.js` — имплементация POM-методов
211
+ 6. `selenium-python.js` — имплементация POM-методов
212
+ 7. `selenium-java.js` — имплементация POM-методов
213
+ 8. `tool-schemas.js` — новые параметры
214
+ 9. `tool-definitions.js` — обновить descriptions + schema
215
+ 10. `index.js` — оркестрация в хендлерах экспорта
216
+ 11. `README.md` — документация
217
+
218
+ ## Верификация
219
+
220
+ 1. Записать сценарий на тестовой странице (например, Google Search)
221
+ 2. Вызвать `exportScenarioAsCode` с `pageObjectMode: 'generate-integrated'`
222
+ 3. Проверить что тест-файл содержит import POM-класса и вызывает его методы
223
+ 4. Вызвать `generatePageObject`, сохранить файл, затем `exportScenarioAsCode` с `pageObjectMode: 'use-existing'`
224
+ 5. Проверить что тест использует существующий POM
225
+ 6. Проверить fallback: экшны без матча → raw-селекторы
226
+ 7. Проверить все 4 фреймворка
227
+ 8. Проверить `appendScenarioToFile` с POM-интеграцией