playwright-genie 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vijay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,435 @@
1
+ # playwright-nlp-locator
2
+
3
+ > 🎯 Find Playwright locators using natural language descriptions powered by LLM
4
+
5
+ [![npm version](https://img.shields.io/npm/v/playwright-nlp-locator.svg)](https://www.npmjs.com/package/playwright-nlp-locator)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ **playwright-nlp-locator** enables you to write browser automation scripts using plain English instead of manually inspecting elements and writing complex selectors. Simply describe the element you want to interact with, and the library will find the best Playwright locator for it.
9
+
10
+ ## ✨ Features
11
+
12
+ - 🗣️ **Natural Language Descriptions** - Describe elements in plain English
13
+ - 🎯 **Smart Locator Generation** - Returns optimal locators (role-based > text-based > CSS)
14
+ - 📊 **Confidence Scores** - Know how confident the match is
15
+ - 🔄 **Alternative Suggestions** - Get multiple locator options
16
+ - 🛠️ **TypeScript Support** - Full type definitions included
17
+ - 🤖 **LLM-Powered** - Uses Abacus.AI APIs for intelligent matching
18
+ - 📦 **Production Ready** - Error handling, edge cases, and best practices
19
+
20
+ ## 📦 Installation
21
+
22
+ ```bash
23
+ npm install playwright-nlp-locator playwright
24
+ ```
25
+
26
+ ### Prerequisites
27
+
28
+ 1. **Playwright** - The library works with Playwright
29
+ 2. **Python 3** - Required for LLM API calls
30
+ 3. **Abacus.AI Python SDK** - Install with `pip install abacusai`
31
+ 4. **Abacus.AI API Key** - Set the `ABACUS_API_KEY` environment variable
32
+
33
+ ```bash
34
+ pip install abacusai
35
+ export ABACUS_API_KEY="your-api-key-here"
36
+ ```
37
+
38
+ ## 🚀 Quick Start
39
+
40
+ ```javascript
41
+ const { chromium } = require('playwright');
42
+ const { findLocator, createNLPHelper } = require('playwright-nlp-locator');
43
+
44
+ async function main() {
45
+ const browser = await chromium.launch();
46
+ const page = await browser.newPage();
47
+ await page.goto('https://example.com');
48
+
49
+ // Option 1: Get the locator string
50
+ const result = await findLocator(page, 'Login Button');
51
+ console.log(result.locator); // e.g., "page.getByRole('button', { name: 'Login' })"
52
+ console.log(result.confidence); // e.g., 0.95
53
+
54
+ // Option 2: Use the NLP Helper for direct interaction
55
+ const nlp = createNLPHelper(page);
56
+ await nlp.click('Submit button');
57
+ await nlp.type('Email input field', 'user@example.com');
58
+ await nlp.type('Password field', 'secret123');
59
+
60
+ await browser.close();
61
+ }
62
+
63
+ main();
64
+ ```
65
+
66
+ ## 📖 API Reference
67
+
68
+ ### `findLocator(page, description, options?)`
69
+
70
+ Find a Playwright locator using natural language description.
71
+
72
+ **Parameters:**
73
+ - `page` - Playwright Page object
74
+ - `description` - Natural language description of the element
75
+ - `options` - Optional configuration object
76
+
77
+ **Returns:** `Promise<FindLocatorResult>`
78
+
79
+ ```javascript
80
+ const result = await findLocator(page, 'email input field');
81
+
82
+ // Result object:
83
+ {
84
+ found: true,
85
+ locator: "page.getByPlaceholder('Enter your email')",
86
+ locatorType: 'placeholder',
87
+ confidence: 0.92,
88
+ explanation: 'Input field with placeholder text indicating email entry',
89
+ alternatives: [
90
+ { locator: "page.locator('#email')", confidence: 0.85 }
91
+ ],
92
+ elementIndex: 3
93
+ }
94
+ ```
95
+
96
+ ### `getLocator(page, description, options?)`
97
+
98
+ Get an actual Playwright Locator object ready for interaction.
99
+
100
+ ```javascript
101
+ const { locator, result } = await getLocator(page, 'Submit button');
102
+
103
+ // Use the locator directly
104
+ await locator.click();
105
+ await locator.fill('text');
106
+ const text = await locator.textContent();
107
+ ```
108
+
109
+ ### `findAllLocators(page, description, options?)`
110
+
111
+ Find multiple matching elements for a description.
112
+
113
+ ```javascript
114
+ const matches = await findAllLocators(page, 'navigation links');
115
+
116
+ // Returns array of matches:
117
+ [
118
+ { locator: "page.getByRole('link', { name: 'Home' })", confidence: 0.90, type: 'role' },
119
+ { locator: "page.getByRole('link', { name: 'About' })", confidence: 0.88, type: 'role' }
120
+ ]
121
+ ```
122
+
123
+ ### `createNLPHelper(page, options?)`
124
+
125
+ Create a helper object with natural language methods.
126
+
127
+ ```javascript
128
+ const nlp = createNLPHelper(page);
129
+
130
+ // Available methods:
131
+ await nlp.click('Login button');
132
+ await nlp.type('Username field', 'john_doe');
133
+ await nlp.select('Country dropdown', 'USA');
134
+ await nlp.hover('Profile menu');
135
+ await nlp.waitFor('Loading spinner to disappear');
136
+ const text = await nlp.getText('Welcome message');
137
+ const exists = await nlp.exists('Error message');
138
+ ```
139
+
140
+ ## ⚙️ Configuration Options
141
+
142
+ ```javascript
143
+ const options = {
144
+ // Maximum elements to analyze (default: 100)
145
+ maxElements: 100,
146
+
147
+ // Include hidden elements (default: false)
148
+ includeHiddenElements: false,
149
+
150
+ // Minimum confidence to accept (default: 0.5)
151
+ confidenceThreshold: 0.5,
152
+
153
+ // LLM model to use (default: 'claude-3-5-sonnet')
154
+ model: 'claude-3-5-sonnet',
155
+
156
+ // Locator preference order
157
+ preferredLocatorOrder: ['role', 'text', 'testId', 'css', 'xpath']
158
+ };
159
+
160
+ const result = await findLocator(page, 'Submit button', options);
161
+ ```
162
+
163
+ ## 🎯 Best Practices for Descriptions
164
+
165
+ ### ✅ Good Descriptions
166
+
167
+ ```javascript
168
+ // Be specific about the element type
169
+ await nlp.click('Login button');
170
+ await nlp.type('Email input field', 'user@example.com');
171
+ await nlp.click('Submit form button');
172
+
173
+ // Include context when needed
174
+ await nlp.click('Add to cart button for the first product');
175
+ await nlp.type('Search box in the header', 'shoes');
176
+
177
+ // Use visual or functional descriptions
178
+ await nlp.click('Red cancel button');
179
+ await nlp.click('Hamburger menu icon');
180
+ await nlp.click('Close modal X button');
181
+ ```
182
+
183
+ ### ❌ Avoid Vague Descriptions
184
+
185
+ ```javascript
186
+ // Too vague - could match multiple elements
187
+ await nlp.click('button');
188
+ await nlp.type('input', 'text');
189
+
190
+ // Better alternatives:
191
+ await nlp.click('primary submit button');
192
+ await nlp.type('username input', 'text');
193
+ ```
194
+
195
+ ## 📚 Complete Examples
196
+
197
+ ### Example 1: Login Form Automation
198
+
199
+ ```javascript
200
+ const { chromium } = require('playwright');
201
+ const { createNLPHelper } = require('playwright-nlp-locator');
202
+
203
+ async function loginAutomation() {
204
+ const browser = await chromium.launch();
205
+ const page = await browser.newPage();
206
+
207
+ await page.goto('https://myapp.com/login');
208
+
209
+ const nlp = createNLPHelper(page);
210
+
211
+ // Fill login form using natural language
212
+ await nlp.type('Username or email input', 'john@example.com');
213
+ await nlp.type('Password field', 'secretPassword123');
214
+
215
+ // Check "Remember me" if it exists
216
+ if (await nlp.exists('Remember me checkbox')) {
217
+ await nlp.click('Remember me checkbox');
218
+ }
219
+
220
+ // Submit the form
221
+ await nlp.click('Sign in button');
222
+
223
+ // Wait for dashboard to load
224
+ await nlp.waitFor('Dashboard header');
225
+
226
+ console.log('Login successful!');
227
+
228
+ await browser.close();
229
+ }
230
+ ```
231
+
232
+ ### Example 2: E-commerce Shopping Flow
233
+
234
+ ```javascript
235
+ async function shoppingFlow() {
236
+ const browser = await chromium.launch();
237
+ const page = await browser.newPage();
238
+ const nlp = createNLPHelper(page);
239
+
240
+ await page.goto('https://shop.example.com');
241
+
242
+ // Search for a product
243
+ await nlp.type('Search bar', 'wireless headphones');
244
+ await nlp.click('Search button');
245
+
246
+ // Filter results
247
+ await nlp.click('Price filter dropdown');
248
+ await nlp.click('Under $100 option');
249
+
250
+ // Select a product
251
+ await nlp.click('First product in the list');
252
+
253
+ // Add to cart
254
+ await nlp.select('Size selector', 'Medium');
255
+ await nlp.click('Add to cart button');
256
+
257
+ // Proceed to checkout
258
+ await nlp.click('Shopping cart icon');
259
+ await nlp.click('Proceed to checkout button');
260
+
261
+ // Fill shipping info
262
+ await nlp.type('First name field', 'John');
263
+ await nlp.type('Last name field', 'Doe');
264
+ await nlp.type('Address line 1', '123 Main St');
265
+ await nlp.type('City input', 'New York');
266
+ await nlp.select('State dropdown', 'NY');
267
+ await nlp.type('Zip code', '10001');
268
+
269
+ await nlp.click('Continue to payment button');
270
+
271
+ await browser.close();
272
+ }
273
+ ```
274
+
275
+ ### Example 3: Form Validation Testing
276
+
277
+ ```javascript
278
+ const { findLocator, getLocator } = require('playwright-nlp-locator');
279
+
280
+ async function testFormValidation() {
281
+ const browser = await chromium.launch();
282
+ const page = await browser.newPage();
283
+
284
+ await page.goto('https://myapp.com/signup');
285
+
286
+ // Submit empty form to trigger validation
287
+ const { locator: submitBtn } = await getLocator(page, 'Submit button');
288
+ await submitBtn.click();
289
+
290
+ // Check for validation errors
291
+ const emailError = await findLocator(page, 'Email validation error message');
292
+ if (emailError.found && emailError.confidence > 0.7) {
293
+ console.log('Email validation working:', emailError.locator);
294
+ }
295
+
296
+ const passwordError = await findLocator(page, 'Password error message');
297
+ if (passwordError.found) {
298
+ const { locator } = await getLocator(page, 'Password error');
299
+ const errorText = await locator.textContent();
300
+ console.log('Password error:', errorText);
301
+ }
302
+
303
+ await browser.close();
304
+ }
305
+ ```
306
+
307
+ ### Example 4: Dynamic Content Handling
308
+
309
+ ```javascript
310
+ async function handleDynamicContent() {
311
+ const browser = await chromium.launch();
312
+ const page = await browser.newPage();
313
+ const nlp = createNLPHelper(page);
314
+
315
+ await page.goto('https://app.example.com');
316
+
317
+ // Wait for dynamic content to load
318
+ await nlp.waitFor('Content loaded indicator');
319
+
320
+ // Handle modals
321
+ if (await nlp.exists('Cookie consent popup')) {
322
+ await nlp.click('Accept cookies button');
323
+ }
324
+
325
+ if (await nlp.exists('Newsletter subscription modal')) {
326
+ await nlp.click('Close modal button');
327
+ }
328
+
329
+ // Interact with lazy-loaded content
330
+ await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
331
+ await nlp.waitFor('Load more button');
332
+ await nlp.click('Load more button');
333
+
334
+ await browser.close();
335
+ }
336
+ ```
337
+
338
+ ## 🔧 Locator Types
339
+
340
+ The library returns different types of locators based on element attributes:
341
+
342
+ | Type | Example | Priority |
343
+ |------|---------|----------|
344
+ | Role | `page.getByRole('button', { name: 'Submit' })` | 1 (Highest) |
345
+ | Text | `page.getByText('Click here')` | 2 |
346
+ | Label | `page.getByLabel('Email address')` | 3 |
347
+ | Placeholder | `page.getByPlaceholder('Enter email')` | 4 |
348
+ | TestId | `page.getByTestId('submit-btn')` | 5 |
349
+ | CSS | `page.locator('button.primary')` | 6 |
350
+ | XPath | `page.locator('//button[@id="submit"]')` | 7 (Lowest) |
351
+
352
+ ## 🐛 Error Handling
353
+
354
+ ```javascript
355
+ const { findLocator, getLocator } = require('playwright-nlp-locator');
356
+
357
+ // Method 1: Check result
358
+ const result = await findLocator(page, 'Missing element');
359
+ if (!result.found) {
360
+ console.log('Element not found:', result.error);
361
+ }
362
+
363
+ if (result.confidence < 0.5) {
364
+ console.log('Low confidence match - may be incorrect');
365
+ }
366
+
367
+ // Method 2: Try-catch with getLocator
368
+ try {
369
+ const { locator } = await getLocator(page, 'Element description');
370
+ await locator.click();
371
+ } catch (error) {
372
+ console.error('Failed to find element:', error.message);
373
+ }
374
+
375
+ // Method 3: Fallback locators
376
+ const result = await findLocator(page, 'Submit button');
377
+ if (result.confidence < 0.7 && result.alternatives?.length > 0) {
378
+ console.log('Using alternative locator:', result.alternatives[0].locator);
379
+ }
380
+ ```
381
+
382
+ ## 🔒 Security Notes
383
+
384
+ - The library sends page DOM structure to the LLM API for analysis
385
+ - Sensitive data in element values may be visible to the API
386
+ - Consider using this in development/testing environments
387
+ - For production, ensure compliance with your data policies
388
+
389
+ ## 📄 TypeScript Usage
390
+
391
+ ```typescript
392
+ import { chromium, Page } from 'playwright';
393
+ import {
394
+ findLocator,
395
+ getLocator,
396
+ createNLPHelper,
397
+ FindLocatorResult,
398
+ NLPHelper,
399
+ NLPLocatorConfig
400
+ } from 'playwright-nlp-locator';
401
+
402
+ async function typedExample(): Promise<void> {
403
+ const browser = await chromium.launch();
404
+ const page: Page = await browser.newPage();
405
+
406
+ const config: NLPLocatorConfig = {
407
+ confidenceThreshold: 0.7,
408
+ maxElements: 50
409
+ };
410
+
411
+ const result: FindLocatorResult = await findLocator(page, 'Login button', config);
412
+
413
+ if (result.found && result.confidence >= 0.7) {
414
+ console.log(`Found: ${result.locator}`);
415
+ }
416
+
417
+ const nlp: NLPHelper = createNLPHelper(page, config);
418
+ await nlp.click('Submit button');
419
+
420
+ await browser.close();
421
+ }
422
+ ```
423
+
424
+ ## 🤝 Contributing
425
+
426
+ Contributions are welcome! Please feel free to submit a Pull Request.
427
+
428
+ ## 📝 License
429
+
430
+ MIT License - see the [LICENSE](LICENSE) file for details.
431
+
432
+ ## 🙏 Acknowledgments
433
+
434
+ - [Playwright](https://playwright.dev/) - The underlying browser automation framework
435
+ - [Abacus.AI](https://abacus.ai/) - LLM API powering the natural language understanding