testdriverai 7.3.11 → 7.3.13
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/.github/skills/testdriver:ai/SKILL.md +204 -0
- package/.github/skills/testdriver:assert/SKILL.md +284 -0
- package/.github/skills/testdriver:aws-setup/SKILL.md +515 -0
- package/.github/skills/testdriver:caching/SKILL.md +124 -0
- package/.github/skills/testdriver:captcha/SKILL.md +159 -0
- package/.github/skills/testdriver:ci-cd/SKILL.md +602 -0
- package/.github/skills/testdriver:click/SKILL.md +286 -0
- package/.github/skills/testdriver:client/SKILL.md +339 -0
- package/.github/skills/testdriver:cloud/SKILL.md +119 -0
- package/.github/skills/testdriver:customizing-devices/SKILL.md +153 -0
- package/.github/skills/testdriver:dashcam/SKILL.md +418 -0
- package/.github/skills/testdriver:debugging-with-screenshots/SKILL.md +271 -0
- package/.github/skills/testdriver:device-config/SKILL.md +317 -0
- package/.github/skills/testdriver:double-click/SKILL.md +102 -0
- package/.github/skills/testdriver:elements/SKILL.md +605 -0
- package/.github/skills/testdriver:enterprise/SKILL.md +114 -0
- package/.github/skills/testdriver:examples/SKILL.md +7 -0
- package/.github/skills/testdriver:exec/SKILL.md +345 -0
- package/.github/skills/testdriver:find/SKILL.md +721 -0
- package/.github/skills/testdriver:focus-application/SKILL.md +293 -0
- package/.github/skills/testdriver:generating-tests/SKILL.md +36 -0
- package/.github/skills/testdriver:hover/SKILL.md +278 -0
- package/.github/skills/testdriver:locating-elements/SKILL.md +71 -0
- package/.github/skills/testdriver:making-assertions/SKILL.md +32 -0
- package/.github/skills/testdriver:mcp-workflow/SKILL.md +410 -0
- package/.github/skills/testdriver:mouse-down/SKILL.md +161 -0
- package/.github/skills/testdriver:mouse-up/SKILL.md +164 -0
- package/.github/skills/testdriver:performing-actions/SKILL.md +51 -0
- package/.github/skills/testdriver:press-keys/SKILL.md +348 -0
- package/.github/skills/testdriver:quickstart/SKILL.md +161 -0
- package/.github/skills/testdriver:reusable-code/SKILL.md +240 -0
- package/.github/skills/testdriver:right-click/SKILL.md +123 -0
- package/.github/skills/testdriver:running-tests/SKILL.md +181 -0
- package/.github/skills/testdriver:screenshot/SKILL.md +167 -0
- package/.github/skills/testdriver:scroll/SKILL.md +299 -0
- package/.github/skills/testdriver:secrets/SKILL.md +115 -0
- package/.github/skills/testdriver:self-hosted/SKILL.md +65 -0
- package/.github/skills/testdriver:test-writer/SKILL.md +451 -0
- package/.github/skills/testdriver:testdriver/SKILL.md +523 -0
- package/.github/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
- package/.github/skills/testdriver:type/SKILL.md +357 -0
- package/.github/skills/testdriver:variables/SKILL.md +111 -0
- package/.github/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
- package/.github/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
- package/.github/workflows/acceptance-windows-scheduled.yaml +6 -1
- package/.github/workflows/acceptance.yaml +0 -36
- package/.github/workflows/update-examples.yaml +53 -0
- package/CHANGELOG.md +8 -0
- package/agent/events.js +1 -0
- package/agent/index.js +8 -0
- package/agent/lib/commands.js +48 -29
- package/agent/lib/redraw.js +3 -1
- package/agent/lib/sandbox.js +166 -14
- package/agent/lib/sdk.js +142 -3
- package/agent/lib/system.js +4 -6
- package/ai/skills/testdriver:ai/SKILL.md +204 -0
- package/ai/skills/testdriver:assert/SKILL.md +315 -0
- package/ai/skills/testdriver:aws-setup/SKILL.md +448 -0
- package/ai/skills/testdriver:caching/SKILL.md +124 -0
- package/ai/skills/testdriver:captcha/SKILL.md +159 -0
- package/ai/skills/testdriver:ci-cd/SKILL.md +602 -0
- package/ai/skills/testdriver:click/SKILL.md +286 -0
- package/ai/skills/testdriver:client/SKILL.md +372 -0
- package/ai/skills/testdriver:cloud/SKILL.md +119 -0
- package/ai/skills/testdriver:customizing-devices/SKILL.md +153 -0
- package/ai/skills/testdriver:dashcam/SKILL.md +418 -0
- package/ai/skills/testdriver:debugging-with-screenshots/SKILL.md +401 -0
- package/ai/skills/testdriver:device-config/SKILL.md +317 -0
- package/ai/skills/testdriver:double-click/SKILL.md +102 -0
- package/ai/skills/testdriver:elements/SKILL.md +605 -0
- package/ai/skills/testdriver:enterprise/SKILL.md +114 -0
- package/ai/skills/testdriver:examples/SKILL.md +7 -0
- package/ai/skills/testdriver:exec/SKILL.md +345 -0
- package/ai/skills/testdriver:find/SKILL.md +745 -0
- package/ai/skills/testdriver:focus-application/SKILL.md +293 -0
- package/ai/skills/testdriver:generating-tests/SKILL.md +36 -0
- package/ai/skills/testdriver:hover/SKILL.md +278 -0
- package/ai/skills/testdriver:locating-elements/SKILL.md +71 -0
- package/ai/skills/testdriver:making-assertions/SKILL.md +32 -0
- package/ai/skills/testdriver:mcp-workflow/SKILL.md +410 -0
- package/ai/skills/testdriver:mouse-down/SKILL.md +161 -0
- package/ai/skills/testdriver:mouse-up/SKILL.md +164 -0
- package/ai/skills/testdriver:ocr/SKILL.md +235 -0
- package/ai/skills/testdriver:performing-actions/SKILL.md +51 -0
- package/ai/skills/testdriver:press-keys/SKILL.md +348 -0
- package/ai/skills/testdriver:quickstart/SKILL.md +146 -0
- package/ai/skills/testdriver:reusable-code/SKILL.md +240 -0
- package/ai/skills/testdriver:right-click/SKILL.md +123 -0
- package/ai/skills/testdriver:running-tests/SKILL.md +185 -0
- package/ai/skills/testdriver:screenshot/SKILL.md +248 -0
- package/ai/skills/testdriver:scroll/SKILL.md +335 -0
- package/ai/skills/testdriver:secrets/SKILL.md +115 -0
- package/ai/skills/testdriver:self-hosted/SKILL.md +65 -0
- package/ai/skills/testdriver:test-writer/SKILL.md +451 -0
- package/ai/skills/testdriver:testdriver/SKILL.md +631 -0
- package/ai/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
- package/ai/skills/testdriver:type/SKILL.md +357 -0
- package/ai/skills/testdriver:variables/SKILL.md +111 -0
- package/ai/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
- package/ai/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
- package/debugger/index.html +12 -2
- package/docs/v7/examples/scroll-keyboard.mdx +1 -1
- package/docs/v7/find.mdx +1 -0
- package/examples/config.mjs +1 -1
- package/examples/findall-coffee-icons.test.mjs +42 -0
- package/examples/flake-diffthreshold-001.test.mjs +9 -0
- package/examples/flake-diffthreshold-01.test.mjs +9 -0
- package/examples/flake-diffthreshold-05.test.mjs +9 -0
- package/examples/{z_flake-noredraw-cache.test.mjs → flake-noredraw-cache.test.mjs} +2 -2
- package/examples/{z_flake-noredraw-nocache.test.mjs → flake-noredraw-nocache.test.mjs} +2 -2
- package/examples/{z_flake-redraw-cache.test.mjs → flake-redraw-cache.test.mjs} +2 -2
- package/examples/{z_flake-redraw-nocache.test.mjs → flake-redraw-nocache.test.mjs} +2 -2
- package/examples/flake-rocket-match.test.mjs +30 -0
- package/examples/{z_flake-shared.mjs → flake-shared.mjs} +2 -2
- package/examples/parse.test.mjs +19 -0
- package/examples/scroll-keyboard.test.mjs +1 -1
- package/interfaces/cli/lib/base.js +6 -0
- package/interfaces/logger.js +51 -13
- package/interfaces/vitest-plugin.mjs +137 -0
- package/lib/core/index.d.ts +22 -0
- package/lib/init-project.js +105 -6
- package/lib/vitest/hooks.mjs +2 -5
- package/lib/vitest/setup-disable-defender.mjs +52 -0
- package/package.json +2 -1
- package/sdk-log-formatter.js +90 -0
- package/sdk.d.ts +88 -51
- package/sdk.js +128 -21
- package/setup/aws/disable-defender.sh +42 -0
- package/vitest.config.mjs +1 -3
- package/examples/z_flake-diffthreshold-001.test.mjs +0 -9
- package/examples/z_flake-diffthreshold-01.test.mjs +0 -9
- package/examples/z_flake-diffthreshold-05.test.mjs +0 -9
- /package/{examples → manual}/captcha-api.test.mjs +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testdriver:mouse-up
|
|
3
|
+
description: Release the mouse button
|
|
4
|
+
---
|
|
5
|
+
<!-- Generated from mouse-up.mdx. DO NOT EDIT. -->
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The `mouseUp()` method releases the mouse button, completing a drag operation or custom mouse gesture that was started with [`mouseDown()`](/v7/mouse-down). You can call it without parameters to release at the current mouse position.
|
|
10
|
+
|
|
11
|
+
## Syntax
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// Release mouse button at current position
|
|
15
|
+
await ai.mouseUp();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
|
|
20
|
+
None. The mouse button is released at the current cursor position.
|
|
21
|
+
|
|
22
|
+
## Returns
|
|
23
|
+
|
|
24
|
+
Returns a `Promise<void>` that resolves when the mouse button is released.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Complete Drag and Drop
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// Start dragging
|
|
32
|
+
await ai.mouseDown('file to drag');
|
|
33
|
+
|
|
34
|
+
// Move to drop location
|
|
35
|
+
await ai.hover('target folder');
|
|
36
|
+
|
|
37
|
+
// Complete the drop
|
|
38
|
+
await ai.mouseUp();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Selecting Multiple Files
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
import { test } from 'vitest';
|
|
45
|
+
import { vscode } from '@testdriver/sdk';
|
|
46
|
+
|
|
47
|
+
test('selects range of files', async () => {
|
|
48
|
+
const { ai } = await vscode();
|
|
49
|
+
|
|
50
|
+
// Click first file
|
|
51
|
+
await ai.click('first-file.js in explorer');
|
|
52
|
+
|
|
53
|
+
// Hold shift and click last file
|
|
54
|
+
await ai.pressKeys('Shift');
|
|
55
|
+
await ai.mouseDown('last-file.js in explorer');
|
|
56
|
+
await ai.mouseUp();
|
|
57
|
+
|
|
58
|
+
// Verify multiple files selected
|
|
59
|
+
const selectedCount = await ai.find('status bar showing file count');
|
|
60
|
+
expect(selectedCount.text).toContain('5 files');
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Drawing Application
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
test('draws a shape', async () => {
|
|
68
|
+
const { ai } = await chrome('https://drawing-app.example.com');
|
|
69
|
+
|
|
70
|
+
// Select pencil tool
|
|
71
|
+
await ai.click('pencil tool');
|
|
72
|
+
|
|
73
|
+
// Draw a line
|
|
74
|
+
await ai.mouseDown('canvas near top-left');
|
|
75
|
+
await ai.hover('canvas center');
|
|
76
|
+
await ai.hover('canvas bottom-right');
|
|
77
|
+
await ai.mouseUp();
|
|
78
|
+
|
|
79
|
+
// Verify drawing exists
|
|
80
|
+
const strokes = await ai.exec('canvas.getContext("2d").getImageData(0,0,100,100)');
|
|
81
|
+
expect(strokes).toBeTruthy();
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Resizing Window Panels
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
test('resizes editor panel', async () => {
|
|
89
|
+
const { ai } = await vscode();
|
|
90
|
+
|
|
91
|
+
// Grab the divider
|
|
92
|
+
await ai.mouseDown('panel resize divider');
|
|
93
|
+
|
|
94
|
+
// Drag to new position
|
|
95
|
+
await ai.hover('position 400 pixels from left');
|
|
96
|
+
|
|
97
|
+
// Release to complete resize
|
|
98
|
+
await ai.mouseUp();
|
|
99
|
+
|
|
100
|
+
// Verify new panel size
|
|
101
|
+
const panel = await ai.find('editor panel');
|
|
102
|
+
expect(panel.width).toBeGreaterThan(350);
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Drag to Reorder List Items
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
import { test } from 'vitest';
|
|
110
|
+
import { chrome } from '@testdriver/sdk';
|
|
111
|
+
|
|
112
|
+
test('reorders tasks in list', async () => {
|
|
113
|
+
const { ai } = await chrome('https://todo-app.example.com');
|
|
114
|
+
|
|
115
|
+
// Start dragging first task
|
|
116
|
+
await ai.mouseDown('drag handle on first task');
|
|
117
|
+
|
|
118
|
+
// Move down to third position
|
|
119
|
+
await ai.hover('third task position');
|
|
120
|
+
|
|
121
|
+
// Drop the task
|
|
122
|
+
await ai.mouseUp();
|
|
123
|
+
|
|
124
|
+
// Verify new order
|
|
125
|
+
const thirdTask = await ai.find('third task in list');
|
|
126
|
+
expect(thirdTask.text).toContain('Original first task');
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Text Selection with Mouse
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
test('selects text with mouse drag', async () => {
|
|
134
|
+
const { ai } = await chrome('https://document.example.com');
|
|
135
|
+
|
|
136
|
+
// Start selection at beginning of word
|
|
137
|
+
await ai.mouseDown('start of "TestDriver" word');
|
|
138
|
+
|
|
139
|
+
// Drag to end of word
|
|
140
|
+
await ai.hover('end of "TestDriver" word');
|
|
141
|
+
|
|
142
|
+
// Complete selection
|
|
143
|
+
await ai.mouseUp();
|
|
144
|
+
|
|
145
|
+
// Verify selection
|
|
146
|
+
const selection = await ai.exec('window.getSelection().toString()');
|
|
147
|
+
expect(selection).toBe('TestDriver');
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Important Notes
|
|
152
|
+
|
|
153
|
+
- `mouseUp()` must be preceded by [`mouseDown()`](/v7/mouse-down) to have an effect
|
|
154
|
+
- Releases the button at the current cursor position
|
|
155
|
+
- Completes any drag or selection operation that was in progress
|
|
156
|
+
- For simple clicks, use [`click()`](/v7/click) instead of mouseDown/mouseUp pair
|
|
157
|
+
|
|
158
|
+
## Related Methods
|
|
159
|
+
|
|
160
|
+
- [`mouseDown()`](/v7/mouse-down) - Press mouse button without releasing
|
|
161
|
+
- [`hover()`](/v7/hover) - Move mouse to element
|
|
162
|
+
- [`click()`](/v7/click) - Complete click (mouseDown + mouseUp)
|
|
163
|
+
- [`doubleClick()`](/v7/double-click) - Double-click on element
|
|
164
|
+
- [`rightClick()`](/v7/right-click) - Right-click for context menu
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testdriver:ocr
|
|
3
|
+
description: Extract all visible text from the screen using OCR
|
|
4
|
+
---
|
|
5
|
+
<!-- Generated from ocr.mdx. DO NOT EDIT. -->
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Extract all visible text from the current screen using Tesseract OCR. Returns structured data including each word's text content, bounding box coordinates, and confidence scores.
|
|
10
|
+
|
|
11
|
+
This method runs OCR on-demand and returns the results immediately. It's useful for:
|
|
12
|
+
- Verifying text content on screen
|
|
13
|
+
- Finding elements by their text when visual matching alone isn't enough
|
|
14
|
+
- Debugging what text TestDriver can "see"
|
|
15
|
+
- Building custom text-based assertions
|
|
16
|
+
|
|
17
|
+
<Note>
|
|
18
|
+
**Performance**: OCR runs server-side using Tesseract.js with a worker pool for fast extraction. A typical screenshot processes in 200-500ms.
|
|
19
|
+
</Note>
|
|
20
|
+
|
|
21
|
+
## Syntax
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const result = await testdriver.ocr()
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Parameters
|
|
28
|
+
|
|
29
|
+
None.
|
|
30
|
+
|
|
31
|
+
## Returns
|
|
32
|
+
|
|
33
|
+
`Promise<OCRResult>` - Object containing extracted text data
|
|
34
|
+
|
|
35
|
+
### OCRResult
|
|
36
|
+
|
|
37
|
+
| Property | Type | Description |
|
|
38
|
+
|----------|------|-------------|
|
|
39
|
+
| `words` | `OCRWord[]` | Array of extracted words with positions |
|
|
40
|
+
| `fullText` | `string` | All text concatenated with spaces |
|
|
41
|
+
| `confidence` | `number` | Overall OCR confidence (0-100) |
|
|
42
|
+
| `imageWidth` | `number` | Width of the analyzed screenshot |
|
|
43
|
+
| `imageHeight` | `number` | Height of the analyzed screenshot |
|
|
44
|
+
|
|
45
|
+
### OCRWord
|
|
46
|
+
|
|
47
|
+
| Property | Type | Description |
|
|
48
|
+
|----------|------|-------------|
|
|
49
|
+
| `content` | `string` | The word's text content |
|
|
50
|
+
| `confidence` | `number` | Confidence score for this word (0-100) |
|
|
51
|
+
| `bbox.x0` | `number` | Left edge X coordinate |
|
|
52
|
+
| `bbox.y0` | `number` | Top edge Y coordinate |
|
|
53
|
+
| `bbox.x1` | `number` | Right edge X coordinate |
|
|
54
|
+
| `bbox.y1` | `number` | Bottom edge Y coordinate |
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### Get All Text on Screen
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const result = await testdriver.ocr();
|
|
62
|
+
console.log(result.fullText);
|
|
63
|
+
// "Welcome to TestDriver Sign In Email Password Submit"
|
|
64
|
+
|
|
65
|
+
console.log(`Found ${result.words.length} words with ${result.confidence}% confidence`);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Check if Text Exists
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
const result = await testdriver.ocr();
|
|
72
|
+
|
|
73
|
+
// Check for error message
|
|
74
|
+
const hasError = result.words.some(w =>
|
|
75
|
+
w.content.toLowerCase().includes('error')
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
if (hasError) {
|
|
79
|
+
console.log('Error message detected on screen');
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Find and Click Text
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const result = await testdriver.ocr();
|
|
87
|
+
|
|
88
|
+
// Find the "Submit" button text
|
|
89
|
+
const submitWord = result.words.find(w => w.content === 'Submit');
|
|
90
|
+
|
|
91
|
+
if (submitWord) {
|
|
92
|
+
// Calculate center of the word's bounding box
|
|
93
|
+
const x = Math.round((submitWord.bbox.x0 + submitWord.bbox.x1) / 2);
|
|
94
|
+
const y = Math.round((submitWord.bbox.y0 + submitWord.bbox.y1) / 2);
|
|
95
|
+
|
|
96
|
+
// Click at those coordinates
|
|
97
|
+
await testdriver.click({ x, y });
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Filter Words by Confidence
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
const result = await testdriver.ocr();
|
|
105
|
+
|
|
106
|
+
// Only use high-confidence words (90%+)
|
|
107
|
+
const reliableWords = result.words.filter(w => w.confidence >= 90);
|
|
108
|
+
|
|
109
|
+
console.log('High confidence words:', reliableWords.map(w => w.content));
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Build Custom Assertions
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import { describe, expect, it } from "vitest";
|
|
116
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
117
|
+
|
|
118
|
+
describe("Login Page", () => {
|
|
119
|
+
it("should show form labels", async (context) => {
|
|
120
|
+
const testdriver = TestDriver(context);
|
|
121
|
+
|
|
122
|
+
await testdriver.provision.chrome({
|
|
123
|
+
url: 'https://myapp.com/login',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const result = await testdriver.ocr();
|
|
127
|
+
|
|
128
|
+
// Assert expected labels are present
|
|
129
|
+
expect(result.fullText).toContain('Email');
|
|
130
|
+
expect(result.fullText).toContain('Password');
|
|
131
|
+
expect(result.fullText).toContain('Sign In');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Debug Screen Content
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
// Useful for debugging what TestDriver can see
|
|
140
|
+
const result = await testdriver.ocr();
|
|
141
|
+
|
|
142
|
+
console.log('=== Screen Text ===');
|
|
143
|
+
console.log(result.fullText);
|
|
144
|
+
console.log('');
|
|
145
|
+
|
|
146
|
+
console.log('=== Word Details ===');
|
|
147
|
+
result.words.forEach((word, i) => {
|
|
148
|
+
console.log(`${i + 1}. "${word.content}" at (${word.bbox.x0}, ${word.bbox.y0}) - ${word.confidence}% confidence`);
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Find Multiple Instances
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const result = await testdriver.ocr();
|
|
156
|
+
|
|
157
|
+
// Find all instances of "Button" text
|
|
158
|
+
const buttons = result.words.filter(w =>
|
|
159
|
+
w.content.toLowerCase() === 'button'
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
console.log(`Found ${buttons.length} buttons on screen`);
|
|
163
|
+
|
|
164
|
+
buttons.forEach((btn, i) => {
|
|
165
|
+
console.log(`Button ${i + 1} at position (${btn.bbox.x0}, ${btn.bbox.y0})`);
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## How It Works
|
|
170
|
+
|
|
171
|
+
1. TestDriver captures a screenshot of the current screen
|
|
172
|
+
2. The image is sent to the TestDriver API
|
|
173
|
+
3. Tesseract.js processes the image server-side with multiple workers
|
|
174
|
+
4. The API returns structured data with text and positions
|
|
175
|
+
5. Bounding box coordinates are scaled to match the original screen resolution
|
|
176
|
+
|
|
177
|
+
<Note>
|
|
178
|
+
OCR works best with clear, readable text. Very small text, unusual fonts, or low-contrast text may have lower confidence scores or be missed entirely.
|
|
179
|
+
</Note>
|
|
180
|
+
|
|
181
|
+
## Best Practices
|
|
182
|
+
|
|
183
|
+
<AccordionGroup>
|
|
184
|
+
<Accordion title="Use find() for element location">
|
|
185
|
+
For locating elements, prefer `find()` which uses AI vision. Use `ocr()` when you need raw text data or want to build custom text-based logic.
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
// Prefer this for clicking elements
|
|
189
|
+
await testdriver.find("Submit button").click();
|
|
190
|
+
|
|
191
|
+
// Use ocr() for text verification or custom logic
|
|
192
|
+
const result = await testdriver.ocr();
|
|
193
|
+
expect(result.fullText).toContain('Success');
|
|
194
|
+
```
|
|
195
|
+
</Accordion>
|
|
196
|
+
|
|
197
|
+
<Accordion title="Filter by confidence">
|
|
198
|
+
OCR can sometimes misread characters. Filter by confidence score when accuracy is critical.
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const result = await testdriver.ocr();
|
|
202
|
+
const reliable = result.words.filter(w => w.confidence >= 85);
|
|
203
|
+
```
|
|
204
|
+
</Accordion>
|
|
205
|
+
|
|
206
|
+
<Accordion title="Handle case sensitivity">
|
|
207
|
+
Text matching should usually be case-insensitive since OCR capitalization can vary.
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
const result = await testdriver.ocr();
|
|
211
|
+
const hasLogin = result.words.some(w =>
|
|
212
|
+
w.content.toLowerCase() === 'login'
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
</Accordion>
|
|
216
|
+
|
|
217
|
+
<Accordion title="Wait for content to load">
|
|
218
|
+
If text isn't being found, the page may not be fully loaded. Add a wait or use `waitForText()`.
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Wait for specific text to appear
|
|
222
|
+
await testdriver.waitForText("Welcome");
|
|
223
|
+
|
|
224
|
+
// Then run OCR
|
|
225
|
+
const result = await testdriver.ocr();
|
|
226
|
+
```
|
|
227
|
+
</Accordion>
|
|
228
|
+
</AccordionGroup>
|
|
229
|
+
|
|
230
|
+
## Related
|
|
231
|
+
|
|
232
|
+
- [find()](/v7/find) - AI-powered element location
|
|
233
|
+
- [assert()](/v7/assert) - Make AI-powered assertions about screen state
|
|
234
|
+
- [waitForText()](/v7/waiting-for-elements) - Wait for text to appear on screen
|
|
235
|
+
- [screenshot()](/v7/screenshot) - Capture screenshots
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testdriver:performing-actions
|
|
3
|
+
description: Click, type, hover, scroll and more with TestDriver
|
|
4
|
+
---
|
|
5
|
+
<!-- Generated from performing-actions.mdx. DO NOT EDIT. -->
|
|
6
|
+
|
|
7
|
+
## Performing Actions
|
|
8
|
+
|
|
9
|
+
TestDriver provides a variety of actions you can perform, like [clicking](/v7/click), [typing](/v7/type), [hovering](/v7/hover), and [scrolling](/v7/scroll). For a full list, see the [API Reference](/v7/click).
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// Clicking
|
|
13
|
+
await testdriver.find('submit button').click();
|
|
14
|
+
await testdriver.find('file item').doubleClick();
|
|
15
|
+
await testdriver.find('text area').rightClick();
|
|
16
|
+
|
|
17
|
+
// Typing
|
|
18
|
+
await testdriver.find('email input').type('user@example.com');
|
|
19
|
+
await testdriver.find('password input').type('secret', { secret: true });
|
|
20
|
+
|
|
21
|
+
// Keyboard shortcuts
|
|
22
|
+
await testdriver.pressKeys(['enter']);
|
|
23
|
+
await testdriver.pressKeys(['ctrl', 'c']);
|
|
24
|
+
|
|
25
|
+
// Hovering
|
|
26
|
+
await testdriver.find('dropdown menu').hover();
|
|
27
|
+
|
|
28
|
+
// Scrolling
|
|
29
|
+
await testdriver.scroll('down', 500);
|
|
30
|
+
await testdriver.scrollUntilText('Footer content');
|
|
31
|
+
|
|
32
|
+
// Extracting information from screen
|
|
33
|
+
const price = await testdriver.extract('the total price');
|
|
34
|
+
const orderNumber = await testdriver.extract('the order confirmation number');
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Chaining Actions
|
|
38
|
+
|
|
39
|
+
TestDriver supports method chaining for cleaner code:
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
// Chain find() with actions
|
|
43
|
+
const button = await testdriver.find('submit button').click();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or save element reference for later use:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
const button = await testdriver.find('submit button');
|
|
50
|
+
await button.click();
|
|
51
|
+
```
|