sentience-ts 0.10.3 → 0.10.5
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/README.md +405 -99
- package/dist/actions.d.ts +47 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +245 -9
- package/dist/actions.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/wait.d.ts +14 -1
- package/dist/wait.d.ts.map +1 -1
- package/dist/wait.js +29 -3
- package/dist/wait.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
**📜 License**: Apache License 2.0
|
|
4
4
|
|
|
5
|
-
TypeScript SDK for Sentience AI Agent Browser Automation.
|
|
5
|
+
TypeScript/JavaScript SDK for Sentience AI Agent Browser Automation. Build intelligent web automation agents that can see, understand, and interact with web pages like humans do.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
cd sdk-ts
|
|
11
10
|
npm install
|
|
12
11
|
npm run build
|
|
13
12
|
|
|
@@ -21,20 +20,20 @@ npx playwright install chromium
|
|
|
21
20
|
import { SentienceBrowser, snapshot, find, click } from './src';
|
|
22
21
|
|
|
23
22
|
async function main() {
|
|
24
|
-
const browser = new SentienceBrowser(
|
|
25
|
-
|
|
23
|
+
const browser = new SentienceBrowser();
|
|
24
|
+
|
|
26
25
|
try {
|
|
27
26
|
await browser.start();
|
|
28
|
-
|
|
29
|
-
await browser.
|
|
27
|
+
|
|
28
|
+
await browser.goto('https://example.com');
|
|
30
29
|
await browser.getPage().waitForLoadState('networkidle');
|
|
31
|
-
|
|
32
|
-
// Take snapshot
|
|
30
|
+
|
|
31
|
+
// Take snapshot - captures all interactive elements
|
|
33
32
|
const snap = await snapshot(browser);
|
|
34
33
|
console.log(`Found ${snap.elements.length} elements`);
|
|
35
|
-
|
|
36
|
-
// Find and click a link
|
|
37
|
-
const link = find(snap, 'role=link');
|
|
34
|
+
|
|
35
|
+
// Find and click a link using semantic selectors
|
|
36
|
+
const link = find(snap, 'role=link text~"More information"');
|
|
38
37
|
if (link) {
|
|
39
38
|
const result = await click(browser, link.id);
|
|
40
39
|
console.log(`Click success: ${result.success}`);
|
|
@@ -43,131 +42,259 @@ async function main() {
|
|
|
43
42
|
await browser.close();
|
|
44
43
|
}
|
|
45
44
|
}
|
|
45
|
+
|
|
46
|
+
main();
|
|
46
47
|
```
|
|
47
48
|
|
|
49
|
+
## Real-World Example: Amazon Shopping Bot
|
|
50
|
+
|
|
51
|
+
This example demonstrates navigating Amazon, finding products, and adding items to cart:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { SentienceBrowser, snapshot, find, click } from './src';
|
|
55
|
+
|
|
56
|
+
async function main() {
|
|
57
|
+
const browser = new SentienceBrowser(undefined, undefined, false);
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
await browser.start();
|
|
61
|
+
|
|
62
|
+
// Navigate to Amazon Best Sellers
|
|
63
|
+
await browser.goto('https://www.amazon.com/gp/bestsellers/');
|
|
64
|
+
await browser.getPage().waitForLoadState('networkidle');
|
|
65
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
66
|
+
|
|
67
|
+
// Take snapshot and find products
|
|
68
|
+
const snap = await snapshot(browser);
|
|
69
|
+
console.log(`Found ${snap.elements.length} elements`);
|
|
70
|
+
|
|
71
|
+
// Find first product in viewport using spatial filtering
|
|
72
|
+
const products = snap.elements
|
|
73
|
+
.filter(el =>
|
|
74
|
+
el.role === 'link' &&
|
|
75
|
+
el.visual_cues.is_clickable &&
|
|
76
|
+
el.in_viewport &&
|
|
77
|
+
!el.is_occluded &&
|
|
78
|
+
el.bbox.y < 600 // First row
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (products.length > 0) {
|
|
82
|
+
// Sort by position (left to right, top to bottom)
|
|
83
|
+
products.sort((a, b) => a.bbox.y - b.bbox.y || a.bbox.x - b.bbox.x);
|
|
84
|
+
const firstProduct = products[0];
|
|
85
|
+
|
|
86
|
+
console.log(`Clicking: ${firstProduct.text}`);
|
|
87
|
+
const result = await click(browser, firstProduct.id);
|
|
88
|
+
|
|
89
|
+
// Wait for product page
|
|
90
|
+
await browser.getPage().waitForLoadState('networkidle');
|
|
91
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
92
|
+
|
|
93
|
+
// Find and click "Add to Cart" button
|
|
94
|
+
const productSnap = await snapshot(browser);
|
|
95
|
+
const addToCart = find(productSnap, 'role=button text~"add to cart"');
|
|
96
|
+
|
|
97
|
+
if (addToCart) {
|
|
98
|
+
const cartResult = await click(browser, addToCart.id);
|
|
99
|
+
console.log(`Added to cart: ${cartResult.success}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} finally {
|
|
103
|
+
await browser.close();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
main();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**See the complete tutorial**: [Amazon Shopping Guide](../docs/AMAZON_SHOPPING_GUIDE.md)
|
|
111
|
+
|
|
48
112
|
## Running Examples
|
|
49
113
|
|
|
50
114
|
**⚠️ Important**: You cannot use `node` directly to run TypeScript files. Use one of these methods:
|
|
51
115
|
|
|
52
|
-
|
|
116
|
+
### Option 1: Using npm scripts (recommended)
|
|
53
117
|
```bash
|
|
54
118
|
npm run example:hello
|
|
55
119
|
npm run example:basic
|
|
120
|
+
npm run example:query
|
|
121
|
+
npm run example:wait
|
|
56
122
|
```
|
|
57
123
|
|
|
58
|
-
|
|
124
|
+
### Option 2: Using ts-node directly
|
|
59
125
|
```bash
|
|
60
126
|
npx ts-node examples/hello.ts
|
|
61
127
|
# or if ts-node is installed globally:
|
|
62
128
|
ts-node examples/hello.ts
|
|
63
129
|
```
|
|
64
130
|
|
|
65
|
-
|
|
131
|
+
### Option 3: Compile then run
|
|
66
132
|
```bash
|
|
67
133
|
npm run build
|
|
68
|
-
#
|
|
134
|
+
# Then use compiled JavaScript from dist/
|
|
69
135
|
```
|
|
70
136
|
|
|
71
|
-
## Features
|
|
137
|
+
## Core Features
|
|
72
138
|
|
|
73
|
-
###
|
|
74
|
-
-
|
|
75
|
-
-
|
|
139
|
+
### Browser Control
|
|
140
|
+
- **`SentienceBrowser`** - Playwright browser with Sentience extension pre-loaded
|
|
141
|
+
- **`browser.goto(url)`** - Navigate with automatic extension readiness checks
|
|
142
|
+
- Automatic bot evasion and stealth mode
|
|
143
|
+
- Configurable headless/headed mode
|
|
76
144
|
|
|
77
|
-
###
|
|
78
|
-
-
|
|
145
|
+
### Snapshot - Intelligent Page Analysis
|
|
146
|
+
- **`snapshot(browser, options?)`** - Capture page state with AI-ranked elements
|
|
147
|
+
- Returns semantic elements with roles, text, importance scores, and bounding boxes
|
|
148
|
+
- Optional screenshot capture (PNG/JPEG)
|
|
79
149
|
- TypeScript types for type safety
|
|
80
150
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- Supports `enhance_markdown` option to use improved conversion
|
|
85
|
-
- `screenshot(browser, options)` - Capture standalone screenshot
|
|
86
|
-
- Returns base64-encoded data URL
|
|
87
|
-
- Supports PNG and JPEG formats with quality control
|
|
88
|
-
|
|
89
|
-
### Day 4: Query Engine
|
|
90
|
-
- `query(snapshot, selector)` - Find elements matching selector
|
|
91
|
-
- `find(snapshot, selector)` - Find single best match
|
|
92
|
-
- String DSL: `"role=button text~'Sign in'"`
|
|
93
|
-
- **📖 [Complete DSL Query Guide](docs/QUERY_DSL.md)** - Comprehensive documentation with all operators, fields, and examples
|
|
94
|
-
|
|
95
|
-
### Day 5: Actions
|
|
96
|
-
- `click(browser, elementId)` - Click element
|
|
97
|
-
- `typeText(browser, elementId, text)` - Type into element
|
|
98
|
-
- `press(browser, key)` - Press keyboard key
|
|
99
|
-
|
|
100
|
-
### Day 6: Wait & Assert
|
|
101
|
-
- `waitFor(browser, selector, timeout)` - Wait for element
|
|
102
|
-
- `expect(browser, selector)` - Assertion helper
|
|
103
|
-
- `.toExist()`
|
|
104
|
-
- `.toBeVisible()`
|
|
105
|
-
- `.toHaveText(text)`
|
|
106
|
-
- `.toHaveCount(n)`
|
|
151
|
+
**Example:**
|
|
152
|
+
```typescript
|
|
153
|
+
const snap = await snapshot(browser, { screenshot: true });
|
|
107
154
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- `format: "markdown"` - Get high-quality markdown (uses Turndown internally)
|
|
113
|
-
- `format: "text"` - Get plain text
|
|
114
|
-
|
|
115
|
-
**Examples:**
|
|
116
|
-
```typescript
|
|
117
|
-
import { read } from './src';
|
|
118
|
-
|
|
119
|
-
// Get raw HTML (default)
|
|
120
|
-
const result = await read(browser);
|
|
121
|
-
const html = result.content;
|
|
122
|
-
|
|
123
|
-
// Get high-quality markdown (uses Turndown automatically)
|
|
124
|
-
const result = await read(browser, { format: 'markdown' });
|
|
125
|
-
const markdown = result.content;
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
See `examples/read-markdown.ts` for complete examples.
|
|
155
|
+
// Access structured data
|
|
156
|
+
console.log(`URL: ${snap.url}`);
|
|
157
|
+
console.log(`Viewport: ${snap.viewport.width}x${snap.viewport.height}`);
|
|
158
|
+
console.log(`Elements: ${snap.elements.length}`);
|
|
129
159
|
|
|
130
|
-
|
|
160
|
+
// Iterate over elements
|
|
161
|
+
for (const element of snap.elements) {
|
|
162
|
+
console.log(`${element.role}: ${element.text} (importance: ${element.importance})`);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
131
165
|
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- `wait-and-click.ts` - Wait and actions
|
|
137
|
-
- `read-markdown.ts` - Reading page content and converting to markdown
|
|
166
|
+
### Query Engine - Semantic Element Selection
|
|
167
|
+
- **`query(snapshot, selector)`** - Find all matching elements
|
|
168
|
+
- **`find(snapshot, selector)`** - Find single best match (by importance)
|
|
169
|
+
- Powerful query DSL with multiple operators
|
|
138
170
|
|
|
139
|
-
|
|
171
|
+
**Query Examples:**
|
|
172
|
+
```typescript
|
|
173
|
+
// Find by role and text
|
|
174
|
+
const button = find(snap, 'role=button text="Sign in"');
|
|
175
|
+
|
|
176
|
+
// Substring match (case-insensitive)
|
|
177
|
+
const link = find(snap, 'role=link text~"more info"');
|
|
178
|
+
|
|
179
|
+
// Spatial filtering
|
|
180
|
+
const topLeft = find(snap, 'bbox.x<=100 bbox.y<=200');
|
|
181
|
+
|
|
182
|
+
// Multiple conditions (AND logic)
|
|
183
|
+
const primaryBtn = find(snap, 'role=button clickable=true visible=true importance>800');
|
|
184
|
+
|
|
185
|
+
// Prefix/suffix matching
|
|
186
|
+
const startsWith = find(snap, 'text^="Add"');
|
|
187
|
+
const endsWith = find(snap, 'text$="Cart"');
|
|
188
|
+
|
|
189
|
+
// Numeric comparisons
|
|
190
|
+
const important = query(snap, 'importance>=700');
|
|
191
|
+
const firstRow = query(snap, 'bbox.y<600');
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**📖 [Complete Query DSL Guide](docs/QUERY_DSL.md)** - All operators, fields, and advanced patterns
|
|
195
|
+
|
|
196
|
+
### Actions - Interact with Elements
|
|
197
|
+
- **`click(browser, elementId)`** - Click element by ID
|
|
198
|
+
- **`clickRect(browser, rect)`** - Click at center of rectangle (coordinate-based)
|
|
199
|
+
- **`typeText(browser, elementId, text)`** - Type into input fields
|
|
200
|
+
- **`press(browser, key)`** - Press keyboard keys (Enter, Escape, Tab, etc.)
|
|
201
|
+
|
|
202
|
+
All actions return `ActionResult` with success status, timing, and outcome:
|
|
140
203
|
|
|
141
204
|
```typescript
|
|
142
|
-
|
|
205
|
+
const result = await click(browser, element.id);
|
|
143
206
|
|
|
144
|
-
|
|
145
|
-
|
|
207
|
+
console.log(`Success: ${result.success}`);
|
|
208
|
+
console.log(`Outcome: ${result.outcome}`); // "navigated", "dom_updated", "error"
|
|
209
|
+
console.log(`Duration: ${result.duration_ms}ms`);
|
|
210
|
+
console.log(`URL changed: ${result.url_changed}`);
|
|
211
|
+
```
|
|
146
212
|
|
|
147
|
-
|
|
148
|
-
|
|
213
|
+
**Coordinate-based clicking:**
|
|
214
|
+
```typescript
|
|
215
|
+
import { clickRect } from './src';
|
|
216
|
+
|
|
217
|
+
// Click at center of rectangle (x, y, width, height)
|
|
218
|
+
await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 });
|
|
219
|
+
|
|
220
|
+
// With visual highlight (default: red border for 2 seconds)
|
|
221
|
+
await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, true, 2.0);
|
|
222
|
+
|
|
223
|
+
// Using element's bounding box
|
|
224
|
+
const snap = await snapshot(browser);
|
|
225
|
+
const element = find(snap, 'role=button');
|
|
226
|
+
if (element) {
|
|
227
|
+
await clickRect(browser, {
|
|
228
|
+
x: element.bbox.x,
|
|
229
|
+
y: element.bbox.y,
|
|
230
|
+
w: element.bbox.width,
|
|
231
|
+
h: element.bbox.height
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
```
|
|
149
235
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
enhance_markdown: true
|
|
154
|
-
});
|
|
155
|
-
console.log(result.content); // High-quality markdown
|
|
236
|
+
### Wait & Assertions
|
|
237
|
+
- **`waitFor(browser, selector, timeout?, interval?, useApi?)`** - Wait for element to appear
|
|
238
|
+
- **`expect(browser, selector)`** - Assertion helper with fluent API
|
|
156
239
|
|
|
157
|
-
|
|
240
|
+
**Examples:**
|
|
241
|
+
```typescript
|
|
242
|
+
// Wait for element (auto-detects optimal interval based on API usage)
|
|
243
|
+
const result = await waitFor(browser, 'role=button text="Submit"', 10000);
|
|
244
|
+
if (result.found) {
|
|
245
|
+
console.log(`Found after ${result.duration_ms}ms`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Use local extension with fast polling (250ms interval)
|
|
249
|
+
const result = await waitFor(browser, 'role=button', 5000, undefined, false);
|
|
250
|
+
|
|
251
|
+
// Use remote API with network-friendly polling (1500ms interval)
|
|
252
|
+
const result = await waitFor(browser, 'role=button', 5000, undefined, true);
|
|
253
|
+
|
|
254
|
+
// Custom interval override
|
|
255
|
+
const result = await waitFor(browser, 'role=button', 5000, 500, false);
|
|
256
|
+
|
|
257
|
+
// Semantic wait conditions
|
|
258
|
+
await waitFor(browser, 'clickable=true', 5000); // Wait for clickable element
|
|
259
|
+
await waitFor(browser, 'importance>100', 5000); // Wait for important element
|
|
260
|
+
await waitFor(browser, 'role=link visible=true', 5000); // Wait for visible link
|
|
261
|
+
|
|
262
|
+
// Assertions
|
|
263
|
+
await expect(browser, 'role=button text="Submit"').toExist(5000);
|
|
264
|
+
await expect(browser, 'role=heading').toBeVisible();
|
|
265
|
+
await expect(browser, 'role=button').toHaveText('Submit');
|
|
266
|
+
await expect(browser, 'role=link').toHaveCount(10);
|
|
158
267
|
```
|
|
159
268
|
|
|
160
|
-
###
|
|
269
|
+
### Content Reading
|
|
270
|
+
- **`read(browser, options?)`** - Extract page content
|
|
271
|
+
- `format: "text"` - Plain text extraction
|
|
272
|
+
- `format: "markdown"` - High-quality markdown conversion (uses Turndown)
|
|
273
|
+
- `format: "raw"` - Cleaned HTML (default)
|
|
161
274
|
|
|
275
|
+
**Example:**
|
|
162
276
|
```typescript
|
|
163
|
-
import {
|
|
164
|
-
import { writeFileSync } from 'fs';
|
|
277
|
+
import { read } from './src';
|
|
165
278
|
|
|
166
|
-
|
|
167
|
-
await browser
|
|
279
|
+
// Get markdown content
|
|
280
|
+
const result = await read(browser, { format: 'markdown' });
|
|
281
|
+
console.log(result.content); // Markdown text
|
|
168
282
|
|
|
169
|
-
|
|
170
|
-
await browser
|
|
283
|
+
// Get plain text
|
|
284
|
+
const result = await read(browser, { format: 'text' });
|
|
285
|
+
console.log(result.content); // Plain text
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Screenshots
|
|
289
|
+
- **`screenshot(browser, options?)`** - Standalone screenshot capture
|
|
290
|
+
- Returns base64-encoded data URL
|
|
291
|
+
- PNG or JPEG format
|
|
292
|
+
- Quality control for JPEG (1-100)
|
|
293
|
+
|
|
294
|
+
**Example:**
|
|
295
|
+
```typescript
|
|
296
|
+
import { screenshot } from './src';
|
|
297
|
+
import { writeFileSync } from 'fs';
|
|
171
298
|
|
|
172
299
|
// Capture PNG screenshot
|
|
173
300
|
const dataUrl = await screenshot(browser, { format: 'png' });
|
|
@@ -177,17 +304,196 @@ const base64Data = dataUrl.split(',')[1];
|
|
|
177
304
|
const imageData = Buffer.from(base64Data, 'base64');
|
|
178
305
|
writeFileSync('screenshot.png', imageData);
|
|
179
306
|
|
|
180
|
-
|
|
307
|
+
// JPEG with quality control (smaller file size)
|
|
308
|
+
const dataUrl = await screenshot(browser, { format: 'jpeg', quality: 85 });
|
|
181
309
|
```
|
|
182
310
|
|
|
311
|
+
## Element Properties
|
|
312
|
+
|
|
313
|
+
Elements returned by `snapshot()` have the following properties:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
element.id // Unique identifier for interactions
|
|
317
|
+
element.role // ARIA role (button, link, textbox, heading, etc.)
|
|
318
|
+
element.text // Visible text content
|
|
319
|
+
element.importance // AI importance score (0-1000)
|
|
320
|
+
element.bbox // Bounding box (x, y, width, height)
|
|
321
|
+
element.visual_cues // Visual analysis (is_primary, is_clickable, background_color)
|
|
322
|
+
element.in_viewport // Is element visible in current viewport?
|
|
323
|
+
element.is_occluded // Is element covered by other elements?
|
|
324
|
+
element.z_index // CSS stacking order
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Query DSL Reference
|
|
328
|
+
|
|
329
|
+
### Basic Operators
|
|
330
|
+
|
|
331
|
+
| Operator | Description | Example |
|
|
332
|
+
|----------|-------------|---------|
|
|
333
|
+
| `=` | Exact match | `role=button` |
|
|
334
|
+
| `!=` | Exclusion | `role!=link` |
|
|
335
|
+
| `~` | Substring (case-insensitive) | `text~"sign in"` |
|
|
336
|
+
| `^=` | Prefix match | `text^="Add"` |
|
|
337
|
+
| `$=` | Suffix match | `text$="Cart"` |
|
|
338
|
+
| `>`, `>=` | Greater than | `importance>500` |
|
|
339
|
+
| `<`, `<=` | Less than | `bbox.y<600` |
|
|
340
|
+
|
|
341
|
+
### Supported Fields
|
|
342
|
+
|
|
343
|
+
- **Role**: `role=button|link|textbox|heading|...`
|
|
344
|
+
- **Text**: `text`, `text~`, `text^=`, `text$=`
|
|
345
|
+
- **Visibility**: `clickable=true|false`, `visible=true|false`
|
|
346
|
+
- **Importance**: `importance`, `importance>=N`, `importance<N`
|
|
347
|
+
- **Position**: `bbox.x`, `bbox.y`, `bbox.width`, `bbox.height`
|
|
348
|
+
- **Layering**: `z_index`
|
|
349
|
+
|
|
350
|
+
## Examples
|
|
351
|
+
|
|
352
|
+
See the `examples/` directory for complete working examples:
|
|
353
|
+
|
|
354
|
+
- **`hello.ts`** - Extension bridge verification
|
|
355
|
+
- **`basic-agent.ts`** - Basic snapshot and element inspection
|
|
356
|
+
- **`query-demo.ts`** - Query engine demonstrations
|
|
357
|
+
- **`wait-and-click.ts`** - Waiting for elements and performing actions
|
|
358
|
+
- **`read-markdown.ts`** - Content extraction and markdown conversion
|
|
359
|
+
|
|
183
360
|
## Testing
|
|
184
361
|
|
|
185
362
|
```bash
|
|
363
|
+
# Run all tests
|
|
186
364
|
npm test
|
|
365
|
+
|
|
366
|
+
# Run with coverage
|
|
367
|
+
npm run test:coverage
|
|
368
|
+
|
|
369
|
+
# Run specific test file
|
|
370
|
+
npm test -- snapshot.test.ts
|
|
187
371
|
```
|
|
188
372
|
|
|
373
|
+
## Configuration
|
|
374
|
+
|
|
375
|
+
### Viewport Size
|
|
376
|
+
|
|
377
|
+
Default viewport is **1280x800** pixels. You can customize it using Playwright's API:
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
const browser = new SentienceBrowser();
|
|
381
|
+
await browser.start();
|
|
382
|
+
|
|
383
|
+
// Set custom viewport before navigating
|
|
384
|
+
await browser.getPage().setViewportSize({ width: 1920, height: 1080 });
|
|
385
|
+
|
|
386
|
+
await browser.goto('https://example.com');
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Headless Mode
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Headed mode (shows browser window)
|
|
393
|
+
const browser = new SentienceBrowser(undefined, undefined, false);
|
|
394
|
+
|
|
395
|
+
// Headless mode
|
|
396
|
+
const browser = new SentienceBrowser(undefined, undefined, true);
|
|
397
|
+
|
|
398
|
+
// Auto-detect based on environment (default)
|
|
399
|
+
const browser = new SentienceBrowser(); // headless=true if CI=true, else false
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## Best Practices
|
|
403
|
+
|
|
404
|
+
### 1. Wait for Dynamic Content
|
|
405
|
+
```typescript
|
|
406
|
+
await browser.goto('https://example.com');
|
|
407
|
+
await browser.getPage().waitForLoadState('networkidle');
|
|
408
|
+
await new Promise(resolve => setTimeout(resolve, 1000)); // Extra buffer
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### 2. Use Multiple Strategies for Finding Elements
|
|
412
|
+
```typescript
|
|
413
|
+
// Try exact match first
|
|
414
|
+
let btn = find(snap, 'role=button text="Add to Cart"');
|
|
415
|
+
|
|
416
|
+
// Fallback to fuzzy match
|
|
417
|
+
if (!btn) {
|
|
418
|
+
btn = find(snap, 'role=button text~"cart"');
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### 3. Check Element Visibility Before Clicking
|
|
423
|
+
```typescript
|
|
424
|
+
if (element.in_viewport && !element.is_occluded) {
|
|
425
|
+
await click(browser, element.id);
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 4. Handle Navigation
|
|
430
|
+
```typescript
|
|
431
|
+
const result = await click(browser, linkId);
|
|
432
|
+
if (result.url_changed) {
|
|
433
|
+
await browser.getPage().waitForLoadState('networkidle');
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 5. Use Screenshots Sparingly
|
|
438
|
+
```typescript
|
|
439
|
+
// Fast - no screenshot (only element data)
|
|
440
|
+
const snap = await snapshot(browser);
|
|
441
|
+
|
|
442
|
+
// Slower - with screenshot (for debugging/verification)
|
|
443
|
+
const snap = await snapshot(browser, { screenshot: true });
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 6. Always Close Browser
|
|
447
|
+
```typescript
|
|
448
|
+
const browser = new SentienceBrowser();
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
await browser.start();
|
|
452
|
+
// ... your automation code
|
|
453
|
+
} finally {
|
|
454
|
+
await browser.close(); // Always clean up
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Troubleshooting
|
|
459
|
+
|
|
460
|
+
### "Extension failed to load"
|
|
461
|
+
**Solution:** Build the extension first:
|
|
462
|
+
```bash
|
|
463
|
+
cd sentience-chrome
|
|
464
|
+
./build.sh
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### "Cannot use import statement outside a module"
|
|
468
|
+
**Solution:** Don't use `node` directly. Use `ts-node` or npm scripts:
|
|
469
|
+
```bash
|
|
470
|
+
npx ts-node examples/hello.ts
|
|
471
|
+
# or
|
|
472
|
+
npm run example:hello
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### "Element not found"
|
|
476
|
+
**Solutions:**
|
|
477
|
+
- Ensure page is loaded: `await browser.getPage().waitForLoadState('networkidle')`
|
|
478
|
+
- Use `waitFor()`: `await waitFor(browser, 'role=button', 10000)`
|
|
479
|
+
- Debug elements: `console.log(snap.elements.map(el => el.text))`
|
|
480
|
+
|
|
481
|
+
### Button not clickable
|
|
482
|
+
**Solutions:**
|
|
483
|
+
- Check visibility: `element.in_viewport && !element.is_occluded`
|
|
484
|
+
- Scroll to element: `await browser.getPage().evaluate(\`window.sentience_registry[${element.id}].scrollIntoView()\`)`
|
|
485
|
+
|
|
189
486
|
## Documentation
|
|
190
487
|
|
|
191
|
-
- **📖 [
|
|
192
|
-
-
|
|
193
|
-
-
|
|
488
|
+
- **📖 [Amazon Shopping Guide](../docs/AMAZON_SHOPPING_GUIDE.md)** - Complete tutorial with real-world example
|
|
489
|
+
- **📖 [Query DSL Guide](docs/QUERY_DSL.md)** - Advanced query patterns and operators
|
|
490
|
+
- **📄 [API Contract](../spec/SNAPSHOT_V1.md)** - Snapshot API specification
|
|
491
|
+
- **📄 [Type Definitions](../spec/sdk-types.md)** - TypeScript/Python type definitions
|
|
492
|
+
|
|
493
|
+
## License
|
|
494
|
+
|
|
495
|
+
**📜 License**
|
|
496
|
+
|
|
497
|
+
This SDK is licensed under the Apache License 2.0.
|
|
498
|
+
|
|
499
|
+
Note: The SDK communicates with proprietary Sentience services and browser components that are not open source. Access to those components is governed by Sentience's Terms of Service.
|
package/dist/actions.d.ts
CHANGED
|
@@ -2,8 +2,53 @@
|
|
|
2
2
|
* Actions v1 - click, type, press
|
|
3
3
|
*/
|
|
4
4
|
import { SentienceBrowser } from './browser';
|
|
5
|
-
import { ActionResult } from './types';
|
|
6
|
-
export
|
|
5
|
+
import { ActionResult, BBox } from './types';
|
|
6
|
+
export interface ClickRect {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
w?: number;
|
|
10
|
+
width?: number;
|
|
11
|
+
h?: number;
|
|
12
|
+
height?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function click(browser: SentienceBrowser, elementId: number, useMouse?: boolean, takeSnapshot?: boolean): Promise<ActionResult>;
|
|
7
15
|
export declare function typeText(browser: SentienceBrowser, elementId: number, text: string, takeSnapshot?: boolean): Promise<ActionResult>;
|
|
8
16
|
export declare function press(browser: SentienceBrowser, key: string, takeSnapshot?: boolean): Promise<ActionResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Click at the center of a rectangle using Playwright's native mouse simulation.
|
|
19
|
+
* This uses a hybrid approach: calculates center coordinates and uses mouse.click()
|
|
20
|
+
* for realistic event simulation (triggers hover, focus, mousedown, mouseup).
|
|
21
|
+
*
|
|
22
|
+
* @param browser - SentienceBrowser instance
|
|
23
|
+
* @param rect - Rectangle with x, y, w (or width), h (or height) keys, or BBox object
|
|
24
|
+
* @param highlight - Whether to show a red border highlight when clicking (default: true)
|
|
25
|
+
* @param highlightDuration - How long to show the highlight in seconds (default: 2.0)
|
|
26
|
+
* @param takeSnapshot - Whether to take snapshot after action
|
|
27
|
+
* @returns ActionResult
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Click using rect object
|
|
32
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 });
|
|
33
|
+
*
|
|
34
|
+
* // Click using BBox from element
|
|
35
|
+
* const snap = await snapshot(browser);
|
|
36
|
+
* const element = find(snap, "role=button");
|
|
37
|
+
* if (element) {
|
|
38
|
+
* await clickRect(browser, {
|
|
39
|
+
* x: element.bbox.x,
|
|
40
|
+
* y: element.bbox.y,
|
|
41
|
+
* w: element.bbox.width,
|
|
42
|
+
* h: element.bbox.height
|
|
43
|
+
* });
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* // Without highlight
|
|
47
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, false);
|
|
48
|
+
*
|
|
49
|
+
* // Custom highlight duration
|
|
50
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, true, 3.0);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function clickRect(browser: SentienceBrowser, rect: ClickRect | BBox, highlight?: boolean, highlightDuration?: number, takeSnapshot?: boolean): Promise<ActionResult>;
|
|
9
54
|
//# sourceMappingURL=actions.d.ts.map
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAY,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAY,IAAI,EAAE,MAAM,SAAS,CAAC;AAGvD,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4DD,wBAAsB,KAAK,CACzB,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,OAAc,EACxB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CAyGvB;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA6CvB;AAED,wBAAsB,KAAK,CACzB,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EACX,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,SAAS,GAAG,IAAI,EACtB,SAAS,GAAE,OAAc,EACzB,iBAAiB,GAAE,MAAY,EAC/B,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,CAAC,CA2FvB"}
|
package/dist/actions.js
CHANGED
|
@@ -6,20 +6,130 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.click = click;
|
|
7
7
|
exports.typeText = typeText;
|
|
8
8
|
exports.press = press;
|
|
9
|
+
exports.clickRect = clickRect;
|
|
9
10
|
const snapshot_1 = require("./snapshot");
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Highlight a rectangle with a red border overlay
|
|
13
|
+
*/
|
|
14
|
+
async function highlightRect(browser, rect, durationSec = 2.0) {
|
|
15
|
+
const page = browser.getPage();
|
|
16
|
+
const highlightId = `sentience_highlight_${Date.now()}`;
|
|
17
|
+
// Combine all arguments into a single object for Playwright
|
|
18
|
+
const args = {
|
|
19
|
+
rect: {
|
|
20
|
+
x: rect.x,
|
|
21
|
+
y: rect.y,
|
|
22
|
+
w: rect.w || rect.width || 0,
|
|
23
|
+
h: rect.h || rect.height || 0,
|
|
24
|
+
},
|
|
25
|
+
highlightId,
|
|
26
|
+
durationSec,
|
|
27
|
+
};
|
|
28
|
+
await page.evaluate((args) => {
|
|
29
|
+
const { rect, highlightId, durationSec } = args;
|
|
30
|
+
// Create overlay div
|
|
31
|
+
const overlay = document.createElement('div');
|
|
32
|
+
overlay.id = highlightId;
|
|
33
|
+
overlay.style.position = 'fixed';
|
|
34
|
+
overlay.style.left = `${rect.x}px`;
|
|
35
|
+
overlay.style.top = `${rect.y}px`;
|
|
36
|
+
overlay.style.width = `${rect.w}px`;
|
|
37
|
+
overlay.style.height = `${rect.h}px`;
|
|
38
|
+
overlay.style.border = '3px solid red';
|
|
39
|
+
overlay.style.borderRadius = '2px';
|
|
40
|
+
overlay.style.boxSizing = 'border-box';
|
|
41
|
+
overlay.style.pointerEvents = 'none';
|
|
42
|
+
overlay.style.zIndex = '999999';
|
|
43
|
+
overlay.style.backgroundColor = 'rgba(255, 0, 0, 0.1)';
|
|
44
|
+
overlay.style.transition = 'opacity 0.3s ease-out';
|
|
45
|
+
document.body.appendChild(overlay);
|
|
46
|
+
// Remove after duration
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
overlay.style.opacity = '0';
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
if (overlay.parentNode) {
|
|
51
|
+
overlay.parentNode.removeChild(overlay);
|
|
52
|
+
}
|
|
53
|
+
}, 300); // Wait for fade-out transition
|
|
54
|
+
}, durationSec * 1000);
|
|
55
|
+
}, args);
|
|
56
|
+
}
|
|
57
|
+
async function click(browser, elementId, useMouse = true, takeSnapshot = false) {
|
|
11
58
|
const page = browser.getPage();
|
|
12
59
|
const startTime = Date.now();
|
|
13
60
|
const urlBefore = page.url();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
61
|
+
let success;
|
|
62
|
+
if (useMouse) {
|
|
63
|
+
// Hybrid approach: Get element bbox from snapshot, calculate center, use mouse.click()
|
|
64
|
+
try {
|
|
65
|
+
const snap = await (0, snapshot_1.snapshot)(browser);
|
|
66
|
+
const element = snap.elements.find((el) => el.id === elementId);
|
|
67
|
+
if (element) {
|
|
68
|
+
// Calculate center of element bbox
|
|
69
|
+
const centerX = element.bbox.x + element.bbox.width / 2;
|
|
70
|
+
const centerY = element.bbox.y + element.bbox.height / 2;
|
|
71
|
+
// Use Playwright's native mouse click for realistic simulation
|
|
72
|
+
await page.mouse.click(centerX, centerY);
|
|
73
|
+
success = true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Fallback to JS click if element not found in snapshot
|
|
77
|
+
try {
|
|
78
|
+
success = await page.evaluate((id) => {
|
|
79
|
+
return window.sentience.click(id);
|
|
80
|
+
}, elementId);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// Navigation might have destroyed context, assume success if URL changed
|
|
84
|
+
success = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
// Fallback to JS click on error
|
|
90
|
+
try {
|
|
91
|
+
success = await page.evaluate((id) => {
|
|
92
|
+
return window.sentience.click(id);
|
|
93
|
+
}, elementId);
|
|
94
|
+
}
|
|
95
|
+
catch (evalError) {
|
|
96
|
+
// Navigation might have destroyed context, assume success
|
|
97
|
+
success = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Legacy JS-based click
|
|
103
|
+
try {
|
|
104
|
+
success = await page.evaluate((id) => {
|
|
105
|
+
return window.sentience.click(id);
|
|
106
|
+
}, elementId);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// Navigation might have destroyed context, assume success
|
|
110
|
+
success = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
18
113
|
// Wait a bit for navigation/DOM updates
|
|
19
|
-
|
|
114
|
+
try {
|
|
115
|
+
await page.waitForTimeout(500);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// Navigation might have happened, context destroyed
|
|
119
|
+
}
|
|
20
120
|
const durationMs = Date.now() - startTime;
|
|
21
|
-
|
|
22
|
-
|
|
121
|
+
// Check if URL changed (handle navigation gracefully)
|
|
122
|
+
let urlAfter;
|
|
123
|
+
let urlChanged;
|
|
124
|
+
try {
|
|
125
|
+
urlAfter = page.url();
|
|
126
|
+
urlChanged = urlBefore !== urlAfter;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
// Context destroyed due to navigation - assume URL changed
|
|
130
|
+
urlAfter = urlBefore;
|
|
131
|
+
urlChanged = true;
|
|
132
|
+
}
|
|
23
133
|
// Determine outcome
|
|
24
134
|
let outcome;
|
|
25
135
|
if (urlChanged) {
|
|
@@ -34,7 +144,12 @@ async function click(browser, elementId, takeSnapshot = false) {
|
|
|
34
144
|
// Optional snapshot after
|
|
35
145
|
let snapshotAfter;
|
|
36
146
|
if (takeSnapshot) {
|
|
37
|
-
|
|
147
|
+
try {
|
|
148
|
+
snapshotAfter = await (0, snapshot_1.snapshot)(browser);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
// Navigation might have destroyed context
|
|
152
|
+
}
|
|
38
153
|
}
|
|
39
154
|
return {
|
|
40
155
|
success,
|
|
@@ -110,4 +225,125 @@ async function press(browser, key, takeSnapshot = false) {
|
|
|
110
225
|
snapshot_after: snapshotAfter,
|
|
111
226
|
};
|
|
112
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Click at the center of a rectangle using Playwright's native mouse simulation.
|
|
230
|
+
* This uses a hybrid approach: calculates center coordinates and uses mouse.click()
|
|
231
|
+
* for realistic event simulation (triggers hover, focus, mousedown, mouseup).
|
|
232
|
+
*
|
|
233
|
+
* @param browser - SentienceBrowser instance
|
|
234
|
+
* @param rect - Rectangle with x, y, w (or width), h (or height) keys, or BBox object
|
|
235
|
+
* @param highlight - Whether to show a red border highlight when clicking (default: true)
|
|
236
|
+
* @param highlightDuration - How long to show the highlight in seconds (default: 2.0)
|
|
237
|
+
* @param takeSnapshot - Whether to take snapshot after action
|
|
238
|
+
* @returns ActionResult
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* // Click using rect object
|
|
243
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 });
|
|
244
|
+
*
|
|
245
|
+
* // Click using BBox from element
|
|
246
|
+
* const snap = await snapshot(browser);
|
|
247
|
+
* const element = find(snap, "role=button");
|
|
248
|
+
* if (element) {
|
|
249
|
+
* await clickRect(browser, {
|
|
250
|
+
* x: element.bbox.x,
|
|
251
|
+
* y: element.bbox.y,
|
|
252
|
+
* w: element.bbox.width,
|
|
253
|
+
* h: element.bbox.height
|
|
254
|
+
* });
|
|
255
|
+
* }
|
|
256
|
+
*
|
|
257
|
+
* // Without highlight
|
|
258
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, false);
|
|
259
|
+
*
|
|
260
|
+
* // Custom highlight duration
|
|
261
|
+
* await clickRect(browser, { x: 100, y: 200, w: 50, h: 30 }, true, 3.0);
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
async function clickRect(browser, rect, highlight = true, highlightDuration = 2.0, takeSnapshot = false) {
|
|
265
|
+
const page = browser.getPage();
|
|
266
|
+
const startTime = Date.now();
|
|
267
|
+
const urlBefore = page.url();
|
|
268
|
+
// Handle BBox object or ClickRect dict
|
|
269
|
+
let x, y, w, h;
|
|
270
|
+
if ('width' in rect && 'height' in rect && !('w' in rect) && !('h' in rect)) {
|
|
271
|
+
// BBox object (width and height are required in BBox)
|
|
272
|
+
const bbox = rect;
|
|
273
|
+
x = bbox.x;
|
|
274
|
+
y = bbox.y;
|
|
275
|
+
w = bbox.width;
|
|
276
|
+
h = bbox.height;
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// ClickRect dict
|
|
280
|
+
const clickRect = rect;
|
|
281
|
+
x = clickRect.x;
|
|
282
|
+
y = clickRect.y;
|
|
283
|
+
w = clickRect.w || clickRect.width || 0;
|
|
284
|
+
h = clickRect.h || clickRect.height || 0;
|
|
285
|
+
}
|
|
286
|
+
if (w <= 0 || h <= 0) {
|
|
287
|
+
return {
|
|
288
|
+
success: false,
|
|
289
|
+
duration_ms: 0,
|
|
290
|
+
outcome: 'error',
|
|
291
|
+
error: {
|
|
292
|
+
code: 'invalid_rect',
|
|
293
|
+
reason: 'Rectangle width and height must be positive',
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
// Calculate center of rectangle
|
|
298
|
+
const centerX = x + w / 2;
|
|
299
|
+
const centerY = y + h / 2;
|
|
300
|
+
// Show highlight before clicking (if enabled)
|
|
301
|
+
if (highlight) {
|
|
302
|
+
await highlightRect(browser, { x, y, w, h }, highlightDuration);
|
|
303
|
+
// Small delay to ensure highlight is visible
|
|
304
|
+
await page.waitForTimeout(50);
|
|
305
|
+
}
|
|
306
|
+
// Use Playwright's native mouse click for realistic simulation
|
|
307
|
+
let success;
|
|
308
|
+
let errorMsg;
|
|
309
|
+
try {
|
|
310
|
+
await page.mouse.click(centerX, centerY);
|
|
311
|
+
success = true;
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
success = false;
|
|
315
|
+
errorMsg = error instanceof Error ? error.message : String(error);
|
|
316
|
+
}
|
|
317
|
+
// Wait a bit for navigation/DOM updates
|
|
318
|
+
await page.waitForTimeout(500);
|
|
319
|
+
const durationMs = Date.now() - startTime;
|
|
320
|
+
const urlAfter = page.url();
|
|
321
|
+
const urlChanged = urlBefore !== urlAfter;
|
|
322
|
+
// Determine outcome
|
|
323
|
+
let outcome;
|
|
324
|
+
if (urlChanged) {
|
|
325
|
+
outcome = 'navigated';
|
|
326
|
+
}
|
|
327
|
+
else if (success) {
|
|
328
|
+
outcome = 'dom_updated';
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
outcome = 'error';
|
|
332
|
+
}
|
|
333
|
+
// Optional snapshot after
|
|
334
|
+
let snapshotAfter;
|
|
335
|
+
if (takeSnapshot) {
|
|
336
|
+
snapshotAfter = await (0, snapshot_1.snapshot)(browser);
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
success,
|
|
340
|
+
duration_ms: durationMs,
|
|
341
|
+
outcome,
|
|
342
|
+
url_changed: urlChanged,
|
|
343
|
+
snapshot_after: snapshotAfter,
|
|
344
|
+
error: success
|
|
345
|
+
? undefined
|
|
346
|
+
: { code: 'click_failed', reason: errorMsg || 'Click failed' },
|
|
347
|
+
};
|
|
348
|
+
}
|
|
113
349
|
//# sourceMappingURL=actions.js.map
|
package/dist/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":";AAAA;;GAEG;;
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAyEH,sBA8GC;AAED,4BAkDC;AAED,sBAiCC;AAsCD,8BAiGC;AAjZD,yCAAsC;AAWtC;;GAEG;AACH,KAAK,UAAU,aAAa,CAC1B,OAAyB,EACzB,IAAe,EACf,cAAsB,GAAG;IAEzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,uBAAuB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAExD,4DAA4D;IAC5D,MAAM,IAAI,GAAG;QACX,IAAI,EAAE;YACJ,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC;YAC5B,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC;SAC9B;QACD,WAAW;QACX,WAAW;KACZ,CAAC;IAEF,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,IAAwG,EAAE,EAAE;QAC3G,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;QAChD,qBAAqB;QACrB,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,EAAE,GAAG,WAAW,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,eAAe,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,YAAY,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG,sBAAsB,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,uBAAuB,CAAC;QAEnD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEnC,wBAAwB;QACxB,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;YAC5B,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;oBACvB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,+BAA+B;QAC1C,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC,EACD,IAAI,CACL,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,KAAK,CACzB,OAAyB,EACzB,SAAiB,EACjB,WAAoB,IAAI,EACxB,eAAwB,KAAK;IAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,IAAI,OAAgB,CAAC;IAErB,IAAI,QAAQ,EAAE,CAAC;QACb,uFAAuF;QACvF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YAEhE,IAAI,OAAO,EAAE,CAAC;gBACZ,mCAAmC;gBACnC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;gBACxD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBACzD,+DAA+D;gBAC/D,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACzC,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,wDAAwD;gBACxD,IAAI,CAAC;oBACH,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE;wBACnC,OAAQ,MAAc,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC7C,CAAC,EAAE,SAAS,CAAC,CAAC;gBAChB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,yEAAyE;oBACzE,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gCAAgC;YAChC,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE;oBACnC,OAAQ,MAAc,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC7C,CAAC,EAAE,SAAS,CAAC,CAAC;YAChB,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,0DAA0D;gBAC1D,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,wBAAwB;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE;gBACnC,OAAQ,MAAc,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC,EAAE,SAAS,CAAC,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0DAA0D;YAC1D,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oDAAoD;IACtD,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE1C,sDAAsD;IACtD,IAAI,QAAgB,CAAC;IACrB,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,UAAU,GAAG,SAAS,KAAK,QAAQ,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2DAA2D;QAC3D,QAAQ,GAAG,SAAS,CAAC;QACrB,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAwE,CAAC;IAC7E,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,GAAG,WAAW,CAAC;IACxB,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,OAAO,GAAG,aAAa,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC;IAED,0BAA0B;IAC1B,IAAI,aAAmC,CAAC;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0CAA0C;QAC5C,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,aAAa;QAC7B,KAAK,EAAE,OAAO;YACZ,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,oCAAoC,EAAE;KAC3E,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,QAAQ,CAC5B,OAAyB,EACzB,SAAiB,EACjB,IAAY,EACZ,eAAwB,KAAK;IAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE;QACzC,MAAM,EAAE,GAAI,MAAc,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAClD,IAAI,EAAE,EAAE,CAAC;YACP,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,SAAS,CAAC,CAAC;IAEd,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YACnC,OAAO,EAAE,OAAO;YAChB,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,mBAAmB,EAAE;SAC7D,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE/B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,SAAS,KAAK,QAAQ,CAAC;IAE1C,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;IAEzD,IAAI,aAAmC,CAAC;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,aAAa,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,UAAU;QACvB,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,aAAa;KAC9B,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,KAAK,CACzB,OAAyB,EACzB,GAAW,EACX,eAAwB,KAAK;IAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,6BAA6B;IAC7B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,wCAAwC;IACxC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,SAAS,KAAK,QAAQ,CAAC;IAE1C,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;IAEzD,IAAI,aAAmC,CAAC;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,aAAa,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,UAAU;QACvB,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,aAAa;KAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACI,KAAK,UAAU,SAAS,CAC7B,OAAyB,EACzB,IAAsB,EACtB,YAAqB,IAAI,EACzB,oBAA4B,GAAG,EAC/B,eAAwB,KAAK;IAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,uCAAuC;IACvC,IAAI,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,CAAC;IAE/C,IAAI,OAAO,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QAC5E,sDAAsD;QACtD,MAAM,IAAI,GAAG,IAAY,CAAC;QAC1B,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACX,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACX,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACf,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,MAAM,SAAS,GAAG,IAAiB,CAAC;QACpC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;QAChB,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;QAChB,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,SAAS,CAAC,KAAK,IAAI,CAAC,CAAC;QACxC,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,CAAC;YACd,OAAO,EAAE,OAAO;YAChB,KAAK,EAAE;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,6CAA6C;aACtD;SACF,CAAC;IACJ,CAAC;IAED,gCAAgC;IAChC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE1B,8CAA8C;IAC9C,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAChE,6CAA6C;QAC7C,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,+DAA+D;IAC/D,IAAI,OAAgB,CAAC;IACrB,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,KAAK,CAAC;QAChB,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC;IAED,wCAAwC;IACxC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,SAAS,KAAK,QAAQ,CAAC;IAE1C,oBAAoB;IACpB,IAAI,OAAwE,CAAC;IAC7E,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,GAAG,WAAW,CAAC;IACxB,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,OAAO,GAAG,aAAa,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,OAAO,CAAC;IACpB,CAAC;IAED,0BAA0B;IAC1B,IAAI,aAAmC,CAAC;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,aAAa,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO;QACL,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,OAAO;QACP,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,aAAa;QAC7B,KAAK,EAAE,OAAO;YACZ,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,IAAI,cAAc,EAAE;KACjE,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export { SentienceBrowser } from './browser';
|
|
5
5
|
export { snapshot, SnapshotOptions } from './snapshot';
|
|
6
6
|
export { query, find, parseSelector } from './query';
|
|
7
|
-
export { click, typeText, press } from './actions';
|
|
7
|
+
export { click, typeText, press, clickRect, ClickRect } from './actions';
|
|
8
8
|
export { waitFor } from './wait';
|
|
9
9
|
export { expect, Expectation } from './expect';
|
|
10
10
|
export { Inspector, inspect } from './inspector';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC7D,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.screenshot = exports.read = exports.generate = exports.ScriptGenerator = exports.record = exports.Recorder = exports.inspect = exports.Inspector = exports.Expectation = exports.expect = exports.waitFor = exports.press = exports.typeText = exports.click = exports.parseSelector = exports.find = exports.query = exports.snapshot = exports.SentienceBrowser = void 0;
|
|
20
|
+
exports.screenshot = exports.read = exports.generate = exports.ScriptGenerator = exports.record = exports.Recorder = exports.inspect = exports.Inspector = exports.Expectation = exports.expect = exports.waitFor = exports.clickRect = exports.press = exports.typeText = exports.click = exports.parseSelector = exports.find = exports.query = exports.snapshot = exports.SentienceBrowser = void 0;
|
|
21
21
|
var browser_1 = require("./browser");
|
|
22
22
|
Object.defineProperty(exports, "SentienceBrowser", { enumerable: true, get: function () { return browser_1.SentienceBrowser; } });
|
|
23
23
|
var snapshot_1 = require("./snapshot");
|
|
@@ -30,6 +30,7 @@ var actions_1 = require("./actions");
|
|
|
30
30
|
Object.defineProperty(exports, "click", { enumerable: true, get: function () { return actions_1.click; } });
|
|
31
31
|
Object.defineProperty(exports, "typeText", { enumerable: true, get: function () { return actions_1.typeText; } });
|
|
32
32
|
Object.defineProperty(exports, "press", { enumerable: true, get: function () { return actions_1.press; } });
|
|
33
|
+
Object.defineProperty(exports, "clickRect", { enumerable: true, get: function () { return actions_1.clickRect; } });
|
|
33
34
|
var wait_1 = require("./wait");
|
|
34
35
|
Object.defineProperty(exports, "waitFor", { enumerable: true, get: function () { return wait_1.waitFor; } });
|
|
35
36
|
var expect_1 = require("./expect");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;AAEH,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA;AACzB,uCAAuD;AAA9C,oGAAA,QAAQ,OAAA;AACjB,iCAAqD;AAA5C,8FAAA,KAAK,OAAA;AAAE,6FAAA,IAAI,OAAA;AAAE,sGAAA,aAAa,OAAA;AACnC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;AAEH,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA;AACzB,uCAAuD;AAA9C,oGAAA,QAAQ,OAAA;AACjB,iCAAqD;AAA5C,8FAAA,KAAK,OAAA;AAAE,6FAAA,IAAI,OAAA;AAAE,sGAAA,aAAa,OAAA;AACnC,qCAAyE;AAAhE,gGAAA,KAAK,OAAA;AAAE,mGAAA,QAAQ,OAAA;AAAE,gGAAA,KAAK,OAAA;AAAE,oGAAA,SAAS,OAAA;AAC1C,+BAAiC;AAAxB,+FAAA,OAAO,OAAA;AAChB,mCAA+C;AAAtC,gGAAA,MAAM,OAAA;AAAE,qGAAA,WAAW,OAAA;AAC5B,yCAAiD;AAAxC,sGAAA,SAAS,OAAA;AAAE,oGAAA,OAAO,OAAA;AAC3B,uCAAgE;AAAvD,oGAAA,QAAQ,OAAA;AAAoB,kGAAA,MAAM,OAAA;AAC3C,yCAAwD;AAA/C,4GAAA,eAAe,OAAA;AAAE,qGAAA,QAAQ,OAAA;AAClC,+BAAuD;AAA9C,4FAAA,IAAI,OAAA;AACb,2CAA6D;AAApD,wGAAA,UAAU,OAAA;AACnB,0CAAwB"}
|
package/dist/wait.d.ts
CHANGED
|
@@ -3,5 +3,18 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { SentienceBrowser } from './browser';
|
|
5
5
|
import { WaitResult, QuerySelector } from './types';
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Wait for element matching selector to appear
|
|
8
|
+
*
|
|
9
|
+
* @param browser - SentienceBrowser instance
|
|
10
|
+
* @param selector - String DSL or dict query
|
|
11
|
+
* @param timeout - Maximum time to wait (milliseconds). Default: 10000ms (10 seconds)
|
|
12
|
+
* @param interval - Polling interval (milliseconds). If undefined, auto-detects:
|
|
13
|
+
* - 250ms for local extension (useApi=false, fast)
|
|
14
|
+
* - 1500ms for remote API (useApi=true or default, network latency)
|
|
15
|
+
* @param useApi - Force use of server-side API if true, local extension if false.
|
|
16
|
+
* If undefined, uses API if apiKey is set, otherwise uses local extension.
|
|
17
|
+
* @returns WaitResult
|
|
18
|
+
*/
|
|
19
|
+
export declare function waitFor(browser: SentienceBrowser, selector: QuerySelector, timeout?: number, interval?: number, useApi?: boolean): Promise<WaitResult>;
|
|
7
20
|
//# sourceMappingURL=wait.d.ts.map
|
package/dist/wait.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAW,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7D,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,MAAc,EACvB,QAAQ,
|
|
1
|
+
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAW,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7D;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,MAAc,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CA6CrB"}
|
package/dist/wait.js
CHANGED
|
@@ -6,11 +6,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.waitFor = waitFor;
|
|
7
7
|
const snapshot_1 = require("./snapshot");
|
|
8
8
|
const query_1 = require("./query");
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Wait for element matching selector to appear
|
|
11
|
+
*
|
|
12
|
+
* @param browser - SentienceBrowser instance
|
|
13
|
+
* @param selector - String DSL or dict query
|
|
14
|
+
* @param timeout - Maximum time to wait (milliseconds). Default: 10000ms (10 seconds)
|
|
15
|
+
* @param interval - Polling interval (milliseconds). If undefined, auto-detects:
|
|
16
|
+
* - 250ms for local extension (useApi=false, fast)
|
|
17
|
+
* - 1500ms for remote API (useApi=true or default, network latency)
|
|
18
|
+
* @param useApi - Force use of server-side API if true, local extension if false.
|
|
19
|
+
* If undefined, uses API if apiKey is set, otherwise uses local extension.
|
|
20
|
+
* @returns WaitResult
|
|
21
|
+
*/
|
|
22
|
+
async function waitFor(browser, selector, timeout = 10000, interval, useApi) {
|
|
23
|
+
// Auto-detect optimal interval based on API usage
|
|
24
|
+
if (interval === undefined) {
|
|
25
|
+
// Determine if using API
|
|
26
|
+
const willUseApi = useApi !== undefined
|
|
27
|
+
? useApi
|
|
28
|
+
: (browser.getApiKey() !== undefined);
|
|
29
|
+
if (willUseApi) {
|
|
30
|
+
interval = 1500; // Longer interval for API calls (network latency)
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
interval = 250; // Shorter interval for local extension (fast)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
10
36
|
const startTime = Date.now();
|
|
11
37
|
while (Date.now() - startTime < timeout) {
|
|
12
|
-
// Take snapshot
|
|
13
|
-
const snap = await (0, snapshot_1.snapshot)(browser);
|
|
38
|
+
// Take snapshot (may be local extension or remote API)
|
|
39
|
+
const snap = await (0, snapshot_1.snapshot)(browser, { use_api: useApi });
|
|
14
40
|
// Try to find element
|
|
15
41
|
const element = (0, query_1.find)(snap, selector);
|
|
16
42
|
if (element) {
|
package/dist/wait.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":";AAAA;;GAEG;;
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAoBH,0BAmDC;AAnED,yCAAsC;AACtC,mCAA+B;AAE/B;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,OAAO,CAC3B,OAAyB,EACzB,QAAuB,EACvB,UAAkB,KAAK,EACvB,QAAiB,EACjB,MAAgB;IAEhB,kDAAkD;IAClD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,yBAAyB;QACzB,MAAM,UAAU,GAAG,MAAM,KAAK,SAAS;YACrC,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,SAAS,CAAC,CAAC;QACxC,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,GAAG,IAAI,CAAC,CAAC,kDAAkD;QACrE,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,GAAG,CAAC,CAAC,8CAA8C;QAChE,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,OAAO,EAAE,CAAC;QACxC,uDAAuD;QACvD,MAAM,IAAI,GAAG,MAAM,IAAA,mBAAQ,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAE1D,sBAAsB;QACtB,MAAM,OAAO,GAAG,IAAA,YAAI,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAErC,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,OAAO;gBACP,WAAW,EAAE,UAAU;gBACvB,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAED,wBAAwB;QACxB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,UAAU;IACV,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC1C,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,UAAU;QACvB,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|