@testdriverai/agent 7.11.229-canary → 7.11.231-test
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/docs/_data/examples-manifest.json +16 -16
- package/docs/_scripts/generate-examples.js +38 -45
- package/docs/agent.mdx +174 -93
- package/docs/assert.mdx +73 -269
- package/docs/aws-setup.mdx +196 -314
- package/docs/bring-your-own-machine.mdx +139 -206
- package/docs/cache.mdx +144 -151
- package/docs/caching.mdx +99 -89
- package/docs/captcha.mdx +126 -111
- package/docs/ci-cd.mdx +154 -543
- package/docs/click.mdx +74 -229
- package/docs/client.mdx +177 -231
- package/docs/copilot/auto-healing.mdx +86 -370
- package/docs/copilot/running-tests.mdx +121 -930
- package/docs/customizing-devices.mdx +74 -251
- package/docs/dashcam.mdx +72 -405
- package/docs/debugging-with-screenshots.mdx +105 -371
- package/docs/docs.json +75 -18
- package/docs/double-click.mdx +48 -68
- package/docs/errors.mdx +102 -176
- package/docs/events.mdx +170 -327
- package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
- package/docs/examples/assert.mdx +28 -41
- package/docs/examples/click-button.mdx +71 -0
- package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
- package/docs/examples/element-not-found.mdx +27 -26
- package/docs/examples/findall-coffee-icons.mdx +28 -32
- package/docs/examples/installer.mdx +61 -25
- package/docs/examples/launch-vscode-linux.mdx +28 -51
- package/docs/examples/navigate-and-scroll.mdx +82 -0
- package/docs/examples/parse.mdx +24 -28
- package/docs/examples/press-keys.mdx +28 -25
- package/docs/examples/scroll.mdx +25 -27
- package/docs/examples/type.mdx +26 -21
- package/docs/exec.mdx +92 -256
- package/docs/extract.mdx +69 -170
- package/docs/find.mdx +140 -736
- package/docs/focus-application.mdx +69 -246
- package/docs/generating-tests.mdx +103 -137
- package/docs/guide/best-practices-polling.mdx +65 -141
- package/docs/hosted.mdx +80 -144
- package/docs/hover.mdx +62 -235
- package/docs/locating-elements.mdx +74 -369
- package/docs/making-assertions.mdx +116 -74
- package/docs/mcp-setup.mdx +80 -63
- package/docs/mouse-down.mdx +48 -125
- package/docs/mouse-up.mdx +47 -129
- package/docs/options.mdx +75 -48
- package/docs/parse.mdx +95 -184
- package/docs/performing-actions.mdx +104 -94
- package/docs/press-keys.mdx +59 -299
- package/docs/provision.mdx +137 -182
- package/docs/quickstart-claude.mdx +85 -0
- package/docs/quickstart-github.mdx +62 -32
- package/docs/quickstart-manual.mdx +60 -33
- package/docs/quickstart-vscode.mdx +97 -0
- package/docs/quickstart.mdx +25 -9
- package/docs/redraw.mdx +101 -165
- package/docs/reusable-code.mdx +97 -200
- package/docs/right-click.mdx +47 -89
- package/docs/screenshot.mdx +47 -201
- package/docs/screenshots.mdx +87 -137
- package/docs/scroll.mdx +71 -154
- package/docs/secrets.mdx +96 -91
- package/docs/self-hosted.mdx +83 -142
- package/docs/snippets/enterprise.mdx +15 -0
- package/docs/styles.css +68 -0
- package/docs/test-results-json.mdx +167 -204
- package/docs/type.mdx +56 -304
- package/docs/variables.mdx +121 -81
- package/docs/wait.mdx +33 -31
- package/docs/what-is-testdriver.mdx +80 -32
- package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
- package/examples/assert.test.mjs +3 -20
- package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
- package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
- package/examples/element-not-found.test.mjs +3 -5
- package/examples/findall-coffee-icons.test.mjs +3 -3
- package/examples/installer.test.mjs +1 -1
- package/examples/launch-vscode-linux.test.mjs +6 -33
- package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
- package/examples/parse.test.mjs +1 -2
- package/examples/press-keys.test.mjs +4 -4
- package/examples/scroll.test.mjs +3 -6
- package/examples/type.test.mjs +5 -2
- package/lib/provision.js +6 -2
- package/package.json +1 -1
- package/sdk.d.ts +4 -2
- package/sdk.js +1 -1
- package/docs/claude-mcp-plugin.mdx +0 -244
- package/docs/elements.mdx +0 -606
- package/docs/examples/ai.mdx +0 -78
- package/docs/examples/captcha-api.mdx +0 -92
- package/docs/examples/chrome-extension.mdx +0 -156
- package/docs/examples/drag-and-drop.mdx +0 -100
- package/docs/examples/formatted-logging.mdx +0 -74
- package/docs/examples/hover-text.mdx +0 -70
- package/docs/examples/match-image.mdx +0 -97
- package/docs/examples/scroll-keyboard.mdx +0 -80
- package/docs/examples/scroll-until-text.mdx +0 -109
|
@@ -1,28 +1,49 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Set up a project"
|
|
3
3
|
sidebarTitle: "Setting up your workspace"
|
|
4
|
-
description: "Add TestDriver to
|
|
4
|
+
description: "Add TestDriver to your own project and run your first Vitest test."
|
|
5
5
|
icon: "wrench"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
Add TestDriver to
|
|
8
|
+
Add TestDriver to a new or existing project, then run your first test.
|
|
9
|
+
|
|
10
|
+
- **Fastest:** run `npx testdriverai init` and let it create every file for you.
|
|
11
|
+
- **By hand:** follow the steps below to see exactly what each file does.
|
|
9
12
|
|
|
10
13
|
<Tip>
|
|
11
|
-
|
|
14
|
+
Only want to drive TestDriver from chat? [MCP setup](/mcp-setup) needs one URL and nothing installed.
|
|
12
15
|
</Tip>
|
|
13
16
|
|
|
17
|
+
## Set up with init
|
|
18
|
+
|
|
19
|
+
Run `init` in your project folder:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx testdriverai init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
It signs you in and saves your API key to `.env`. It then adds:
|
|
26
|
+
|
|
27
|
+
- A `package.json`, if you don't have one
|
|
28
|
+
- `vitest.config.js` with the TestDriver reporter
|
|
29
|
+
- An example test in `tests/`
|
|
30
|
+
- A GitHub Actions workflow
|
|
31
|
+
- The TestDriver agent and MCP server for your AI client
|
|
32
|
+
|
|
33
|
+
`init` keeps your existing `package.json`, Vitest config, tests, and workflow. It only adds to `.gitignore` and to MCP config files.
|
|
34
|
+
|
|
35
|
+
Then run the example:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx vitest run
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Set up by hand
|
|
42
|
+
|
|
14
43
|
<Steps>
|
|
15
|
-
<Step title="
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
title="Get an API Key"
|
|
19
|
-
icon="user-plus"
|
|
20
|
-
href="https://console.testdriver.ai/settings"
|
|
21
|
-
arrow
|
|
22
|
-
horizontal
|
|
23
|
-
>
|
|
24
|
-
Start with 60 free device minutes, no credit card required.
|
|
25
|
-
</Card>
|
|
44
|
+
<Step title="Add your API key">
|
|
45
|
+
|
|
46
|
+
Create an API key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys). The free plan includes 30 testing minutes and needs no credit card.
|
|
26
47
|
|
|
27
48
|
Save the key in a `.env` file at your project root. The SDK loads it automatically:
|
|
28
49
|
|
|
@@ -30,7 +51,7 @@ If you only want to drive TestDriver from chat, [MCP Setup](/mcp-setup) is a sin
|
|
|
30
51
|
TD_API_KEY=your_api_key
|
|
31
52
|
```
|
|
32
53
|
|
|
33
|
-
Add `.env` to `.gitignore` so the key
|
|
54
|
+
Add `.env` to `.gitignore` so the key isn't committed.
|
|
34
55
|
|
|
35
56
|
</Step>
|
|
36
57
|
<Step title="Install dependencies">
|
|
@@ -41,14 +62,12 @@ If you only want to drive TestDriver from chat, [MCP Setup](/mcp-setup) is a sin
|
|
|
41
62
|
npm install --save-dev vitest testdriverai
|
|
42
63
|
```
|
|
43
64
|
|
|
44
|
-
|
|
45
|
-
TestDriver requires Node.js 20.19 or later and only runs on [Vitest](https://vitest.dev). Jest, Mocha, and other runners are not supported.
|
|
46
|
-
</Note>
|
|
65
|
+
TestDriver needs Node.js 20.19 or later. It only runs on [Vitest](https://vitest.dev), not Jest, Mocha, or other runners.
|
|
47
66
|
|
|
48
67
|
</Step>
|
|
49
68
|
<Step title="Configure Vitest">
|
|
50
69
|
|
|
51
|
-
Create `vitest.config.js` at your project root
|
|
70
|
+
Create `vitest.config.js` at your project root, or add these settings to your existing config:
|
|
52
71
|
|
|
53
72
|
```js vitest.config.js
|
|
54
73
|
import { defineConfig } from 'vitest/config';
|
|
@@ -65,9 +84,9 @@ If you only want to drive TestDriver from chat, [MCP Setup](/mcp-setup) is a sin
|
|
|
65
84
|
});
|
|
66
85
|
```
|
|
67
86
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
87
|
+
- **`TestDriver()`** is the reporter. It records each run in the TestDriver console, with its recording.
|
|
88
|
+
- **`setupFiles`** links your tests to the reporter, so each test's recording attaches to the run.
|
|
89
|
+
- **The timeouts** must be long. Vitest's defaults (5 seconds for tests, 10 for hooks) are too short for a real machine.
|
|
71
90
|
|
|
72
91
|
</Step>
|
|
73
92
|
<Step title="Write a test">
|
|
@@ -99,37 +118,45 @@ If you only want to drive TestDriver from chat, [MCP Setup](/mcp-setup) is a sin
|
|
|
99
118
|
});
|
|
100
119
|
```
|
|
101
120
|
|
|
102
|
-
If your
|
|
121
|
+
If your `package.json` doesn't set `"type": "module"`, name the file `search.test.mjs` instead.
|
|
103
122
|
|
|
104
123
|
</Step>
|
|
105
124
|
<Step title="Run the test">
|
|
106
125
|
|
|
107
126
|
```bash
|
|
108
|
-
vitest run
|
|
127
|
+
npx vitest run
|
|
109
128
|
```
|
|
110
129
|
|
|
111
|
-
A sandbox starts, Chrome opens, and a live preview appears in your browser.
|
|
130
|
+
A sandbox starts, Chrome opens, and a live preview appears in your browser.
|
|
131
|
+
|
|
132
|
+
When the run finishes, open the `TESTDRIVER_RUN_URL` link at the end of the output. It shows the recording and each step.
|
|
112
133
|
|
|
113
134
|
</Step>
|
|
114
135
|
</Steps>
|
|
115
136
|
|
|
116
|
-
##
|
|
137
|
+
## Connect an AI assistant
|
|
117
138
|
|
|
118
|
-
|
|
139
|
+
To write tests with an AI assistant, add the TestDriver agent and MCP server to your project. `--no-sample-test` skips the example test files:
|
|
119
140
|
|
|
120
141
|
```bash
|
|
121
142
|
npx testdriverai init --client cursor,claude-code,vscode --no-sample-test
|
|
122
143
|
```
|
|
123
144
|
|
|
124
|
-
|
|
145
|
+
Your existing config and tests stay as they are. For Claude Code or VS Code, you can use the [plugin](/quickstart-claude) or [extension](/quickstart-vscode) instead.
|
|
125
146
|
|
|
126
147
|
## Next steps
|
|
127
148
|
|
|
128
149
|
<CardGroup cols={2}>
|
|
129
|
-
<Card title="
|
|
130
|
-
|
|
150
|
+
<Card title="Launch apps" icon="rocket" href="/provision">
|
|
151
|
+
Start Chrome, extensions, VS Code, or desktop apps.
|
|
152
|
+
</Card>
|
|
153
|
+
<Card title="Perform actions" icon="arrow-pointer" href="/performing-actions">
|
|
154
|
+
Click, type, scroll, and wait for a changing UI.
|
|
155
|
+
</Card>
|
|
156
|
+
<Card title="Make assertions" icon="circle-check" href="/making-assertions">
|
|
157
|
+
Check what's on screen in plain language.
|
|
131
158
|
</Card>
|
|
132
|
-
<Card title="CI/CD" icon="
|
|
133
|
-
Run tests on every pull request
|
|
159
|
+
<Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
|
|
160
|
+
Run your tests on every pull request.
|
|
134
161
|
</Card>
|
|
135
162
|
</CardGroup>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Add TestDriver to VS Code and Cursor"
|
|
3
|
+
sidebarTitle: "VS Code & Cursor"
|
|
4
|
+
description: "Set up TestDriver in your editor and watch tests run in a live preview panel."
|
|
5
|
+
icon: "code"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Install the TestDriver extension, and your editor's AI assistant can write and run end-to-end tests. You watch the sandbox in a panel beside your code.
|
|
9
|
+
|
|
10
|
+
The extension:
|
|
11
|
+
|
|
12
|
+
- Signs you in.
|
|
13
|
+
- Sets up your project and MCP server.
|
|
14
|
+
- Opens the live preview automatically whenever a test runs.
|
|
15
|
+
|
|
16
|
+
## Before you begin
|
|
17
|
+
|
|
18
|
+
- **VS Code 1.85 or later with GitHub Copilot**, or **Cursor**.
|
|
19
|
+
- **Node.js 20.19 or later**, which runs the MCP server and your tests.
|
|
20
|
+
- **A workspace folder open** in the editor, since the extension sets up TestDriver in it.
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
<Step title="Install the extension">
|
|
24
|
+
|
|
25
|
+
Install [TestDriver.ai from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=testdriver.testdriver), or search for **TestDriver.ai** in the Extensions view.
|
|
26
|
+
|
|
27
|
+
In Cursor, the extension may not appear in search. If so, download it with **Download Extension** on the Marketplace page. Then run **Extensions: Install from VSIX** from the Command Palette and choose the file.
|
|
28
|
+
|
|
29
|
+
</Step>
|
|
30
|
+
<Step title="Sign in">
|
|
31
|
+
|
|
32
|
+
Run **TestDriver: Sign In** from the Command Palette. It opens your browser, signs you in to TestDriver, and saves your API key in the editor.
|
|
33
|
+
|
|
34
|
+
</Step>
|
|
35
|
+
<Step title="Set up your project">
|
|
36
|
+
|
|
37
|
+
Run **TestDriver: Initialize Project**. It writes your API key to `.env` and runs `npx testdriverai init`, which installs the SDK and adds:
|
|
38
|
+
|
|
39
|
+
- An example test
|
|
40
|
+
- The TestDriver agent and skills
|
|
41
|
+
- A Vitest config
|
|
42
|
+
- A GitHub Actions workflow
|
|
43
|
+
|
|
44
|
+
</Step>
|
|
45
|
+
<Step title="Connect the MCP server">
|
|
46
|
+
|
|
47
|
+
Run **TestDriver: Install MCP Server** and choose where to save it: `.vscode/mcp.json` for VS Code or `.cursor/mcp.json` for Cursor.
|
|
48
|
+
|
|
49
|
+
If it asks whether to overwrite an existing TestDriver entry, choose **Yes**. This version of the config turns on the live preview panel.
|
|
50
|
+
|
|
51
|
+
</Step>
|
|
52
|
+
<Step title="Write your first test">
|
|
53
|
+
|
|
54
|
+
In VS Code, run **TestDriver: Chat with Agent**. It opens Copilot chat with the TestDriver agent and a sample prompt.
|
|
55
|
+
|
|
56
|
+
In Cursor, open the chat and ask:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
Use TestDriver to write a test that logs in to https://testdriver-sandbox.vercel.app/login and adds an item to the cart.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The live preview panel opens as the agent starts the sandbox. The agent writes the test under `tests/` as it goes.
|
|
63
|
+
|
|
64
|
+
</Step>
|
|
65
|
+
</Steps>
|
|
66
|
+
|
|
67
|
+
## Extension commands
|
|
68
|
+
|
|
69
|
+
| Command | What it does |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| **TestDriver: Sign In** | Signs in through your browser and saves your API key |
|
|
72
|
+
| **TestDriver: Set API Key** | Saves an API key you paste in instead |
|
|
73
|
+
| **TestDriver: Initialize Project** | Runs `npx testdriverai init` in the workspace |
|
|
74
|
+
| **TestDriver: Install MCP Server** | Adds the TestDriver MCP server to `.vscode/mcp.json` or `.cursor/mcp.json` |
|
|
75
|
+
| **TestDriver: Chat with Agent** | Opens the TestDriver agent in Copilot chat (VS Code) |
|
|
76
|
+
| **TestDriver: Turn into Repeatable Test** | Asks Copilot to turn your session into a test with a GitHub Actions workflow |
|
|
77
|
+
| **TestDriver: Open Live Preview** / **Close Live Preview** | Opens or closes the sandbox preview panel |
|
|
78
|
+
| **TestDriver: Open Getting Started** | Opens the extension's setup walkthrough |
|
|
79
|
+
|
|
80
|
+
The preview panel opens automatically when a test starts. To turn that off, set `testdriverai.autoOpenPreview` to `false` in your settings.
|
|
81
|
+
|
|
82
|
+
## Next steps
|
|
83
|
+
|
|
84
|
+
<CardGroup cols={2}>
|
|
85
|
+
<Card title="Generate tests with AI" icon="compass" href="/generating-tests">
|
|
86
|
+
Prompt the agent and steer it while it works.
|
|
87
|
+
</Card>
|
|
88
|
+
<Card title="Run tests" icon="play" href="/copilot/running-tests">
|
|
89
|
+
Run tests from the editor or the terminal.
|
|
90
|
+
</Card>
|
|
91
|
+
<Card title="Make assertions" icon="circle-check" href="/making-assertions">
|
|
92
|
+
Check what's on screen in plain language.
|
|
93
|
+
</Card>
|
|
94
|
+
<Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
|
|
95
|
+
Run your tests on every pull request.
|
|
96
|
+
</Card>
|
|
97
|
+
</CardGroup>
|
package/docs/quickstart.mdx
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Quickstart"
|
|
3
3
|
sidebarTitle: "Quickstart"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Start with TestDriver from GitHub, Claude Code, VS Code, Cursor, any MCP client, or your own project."
|
|
5
5
|
icon: "rocket"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
TestDriver writes and runs
|
|
8
|
+
TestDriver writes and runs end-to-end tests for web apps, desktop apps, and browser extensions.
|
|
9
|
+
|
|
10
|
+
Each test describes what a user sees and does in plain language. It runs on a real machine in the cloud.
|
|
11
|
+
|
|
12
|
+
Choose where you want to start:
|
|
9
13
|
|
|
10
14
|
<CardGroup cols={1}>
|
|
11
15
|
<Card title="Add to GitHub" icon="github" href="/quickstart-github" arrow horizontal>
|
|
12
|
-
|
|
16
|
+
An AI code reviewer that tests every pull request in a real sandbox.
|
|
17
|
+
</Card>
|
|
18
|
+
<Card title="Claude Code" icon="terminal" href="/quickstart-claude" arrow horizontal>
|
|
19
|
+
Install the plugin to write and run tests from Claude Code.
|
|
13
20
|
</Card>
|
|
14
|
-
<Card title="
|
|
15
|
-
|
|
21
|
+
<Card title="VS Code & Cursor" icon="code" href="/quickstart-vscode" arrow horizontal>
|
|
22
|
+
Install the extension to write tests and watch them run live.
|
|
16
23
|
</Card>
|
|
17
|
-
<Card title="
|
|
18
|
-
Add
|
|
24
|
+
<Card title="Connect your AI client" icon="plug" href="/mcp-setup" arrow horizontal>
|
|
25
|
+
Add one URL to any MCP client, such as Claude or ChatGPT.
|
|
26
|
+
</Card>
|
|
27
|
+
<Card title="Set up a project" icon="wrench" href="/quickstart-manual" arrow horizontal>
|
|
28
|
+
Write and run Vitest tests in your own repository.
|
|
19
29
|
</Card>
|
|
20
30
|
</CardGroup>
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
Not sure? Start with GitHub. Your next pull request gets a review without any setup.
|
|
33
|
+
|
|
34
|
+
Set up a project when you want to write and run tests yourself.
|
|
35
|
+
|
|
36
|
+
<Tip>
|
|
37
|
+
Questions along the way? Ask in the [TestDriver Discord](https://discord.com/invite/cWDFW8DzPm).
|
|
38
|
+
</Tip>
|
package/docs/redraw.mdx
CHANGED
|
@@ -1,216 +1,152 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Wait for the screen to settle"
|
|
3
3
|
sidebarTitle: "Redraw"
|
|
4
|
-
description: "
|
|
4
|
+
description: "Make actions wait until the screen stops changing before the next step runs."
|
|
5
5
|
icon: "rotate"
|
|
6
6
|
mode: "wide"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Redraw detection makes each action wait until the screen has changed and then stopped changing.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- Use it for apps with animations, page transitions, or content that loads after a click.
|
|
12
|
+
- It's off by default. Without it, the next command runs as soon as the action is sent.
|
|
13
|
+
- It can also wait for network traffic in the sandbox to die down.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
**Redraw is disabled by default from v7.3.** Enable it if your tests interact with applications that have many animations or load states.
|
|
15
|
-
</Note>
|
|
15
|
+
## Turn it on
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Pass `redraw: true` when you create the client:
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
```javascript tests/search.test.mjs
|
|
20
|
+
import { describe, expect, it } from 'vitest';
|
|
21
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
describe('Search', () => {
|
|
24
|
+
it('shows results after searching', async (context) => {
|
|
25
|
+
const testdriver = TestDriver(context, { redraw: true });
|
|
26
|
+
await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
// With redraw on, click() returns once the error message has finished drawing
|
|
29
|
+
await testdriver.find('Sign in button below the password field').click();
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
C -- "Yes (frames stable)" --> D[Screen settled ✓]
|
|
31
|
-
B -- "No (waiting...)" --> B
|
|
32
|
-
C -- "No (waiting...)" --> C
|
|
31
|
+
const result = await testdriver.assert('an error says the fields are required');
|
|
32
|
+
expect(result).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
The system polls at **500ms intervals**, comparing screenshot frames. This reduces WebSocket traffic while still providing responsive detection.
|
|
38
|
-
|
|
39
|
-
### Pixel Comparison
|
|
40
|
-
|
|
41
|
-
Uses [pixelmatch](https://github.com/mapbox/pixelmatch) for per-pixel comparison with a threshold of `0.1` for pixel sensitivity. A frame diff above **0.1% of total pixels** indicates the screen has changed.
|
|
42
|
-
|
|
43
|
-
### Z-Score Analysis
|
|
37
|
+
Every click, hover, type, key press, scroll, and `focusApplication()` call now waits for the screen to settle.
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
## What it waits for
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
2. Compute the z-score: `(currentDiff - mean) / stddev`
|
|
49
|
-
3. Screen is stable when `diffPercent < 0.1%` or `z-score < 0` (current diff is below the average)
|
|
41
|
+
TestDriver takes a small screenshot right before the action, then one every 500 ms after it. The screen counts as settled when both of these are true:
|
|
50
42
|
|
|
51
|
-
|
|
43
|
+
1. **The screen changed.** A frame differs from the "before" screenshot by more than 0.1% of its pixels.
|
|
44
|
+
2. **The screen stopped changing.** The latest frame differs from the previous one by less than 0.1%, or by less than the average of the last 10 frames.
|
|
52
45
|
|
|
53
|
-
|
|
46
|
+
If the screen doesn't settle in time, the command carries on anyway. It doesn't throw.
|
|
54
47
|
|
|
55
|
-
|
|
48
|
+
| Command | Waits at most |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `click()`, `doubleClick()`, `rightClick()`, `mouseDown()`, `mouseUp()` | 5 s |
|
|
51
|
+
| `hover()` | 2.5 s |
|
|
52
|
+
| `type()` | 5 s |
|
|
53
|
+
| `pressKeys()` | 5 s |
|
|
54
|
+
| `scroll()` | 5 s |
|
|
55
|
+
| `focusApplication()` | 1 s |
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
| `hover` (within click) | 5000ms | Same as click |
|
|
61
|
-
| `hover` (standalone) | 2500ms | Tooltip animations |
|
|
62
|
-
| `scroll` | 5000ms | Lazy-loaded content |
|
|
63
|
-
| `type` | 5000ms | Autocomplete, validation |
|
|
64
|
-
| `pressKeys` | 5000ms | Keyboard shortcuts may trigger changes |
|
|
65
|
-
| `focusApplication` | 1000ms | Window focus animations |
|
|
57
|
+
<Warning>
|
|
58
|
+
An action that doesn't change the screen never meets the first condition. It waits the full timeout, such as 5 seconds for a click. Turn redraw off for those commands (see below) or leave it off and use [`wait()`](/wait) where you need it.
|
|
59
|
+
</Warning>
|
|
66
60
|
|
|
67
|
-
|
|
61
|
+
## Wait for network traffic too
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
### Constructor Options
|
|
63
|
+
Set `thresholds.network` to also wait until the sandbox's network traffic drops below its recent average:
|
|
72
64
|
|
|
73
65
|
```javascript
|
|
74
|
-
const testdriver =
|
|
75
|
-
|
|
76
|
-
redraw: true, // enable with defaults
|
|
77
|
-
redraw: false, // disable (default since v7.3)
|
|
78
|
-
|
|
79
|
-
// Full configuration
|
|
80
|
-
redraw: {
|
|
81
|
-
enabled: true,
|
|
82
|
-
screenRedraw: true, // enable screen pixel diff detection
|
|
83
|
-
networkMonitor: false, // enable network settling detection
|
|
84
|
-
},
|
|
66
|
+
const testdriver = TestDriver(context, {
|
|
67
|
+
redraw: { thresholds: { network: true } },
|
|
85
68
|
});
|
|
86
69
|
```
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
TestDriver then waits for both the screen and the network to settle, within the same timeouts.
|
|
72
|
+
|
|
73
|
+
To wait for the network only, turn off the screen check with `thresholds: { screen: false, network: true }`.
|
|
74
|
+
|
|
75
|
+
## Options
|
|
76
|
+
|
|
77
|
+
<ParamField path="redraw" type="boolean | object" default="false">
|
|
78
|
+
`true` turns on screen detection. Pass an object to choose what to wait for.
|
|
90
79
|
|
|
91
80
|
<Expandable title="properties">
|
|
92
|
-
<ParamField path="enabled" type="boolean" default=
|
|
93
|
-
|
|
81
|
+
<ParamField path="enabled" type="boolean" default="true">
|
|
82
|
+
Whether redraw detection is on when you pass an object.
|
|
94
83
|
</ParamField>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
84
|
+
<ParamField path="thresholds" type="object">
|
|
85
|
+
<Expandable title="properties">
|
|
86
|
+
<ParamField path="screen" type="number | false">
|
|
87
|
+
Set to `false` to skip the screen check. Any other value leaves it on. The 0.1% change threshold is fixed.
|
|
88
|
+
</ParamField>
|
|
89
|
+
<ParamField path="network" type="boolean" default="false">
|
|
90
|
+
Also wait for network traffic in the sandbox to settle.
|
|
91
|
+
</ParamField>
|
|
92
|
+
</Expandable>
|
|
102
93
|
</ParamField>
|
|
103
94
|
</Expandable>
|
|
104
95
|
</ParamField>
|
|
105
96
|
|
|
106
|
-
|
|
97
|
+
<Note>
|
|
98
|
+
Older tests may use `redrawThreshold`, or `diffThreshold`, `screenRedraw`, and `networkMonitor` inside `redraw`. They still work, but are deprecated. Use `redraw` with `thresholds` instead.
|
|
99
|
+
</Note>
|
|
100
|
+
|
|
101
|
+
## Override it for one command
|
|
107
102
|
|
|
108
|
-
|
|
103
|
+
The client's action methods accept a `redraw` object as an option. It applies to that call only:
|
|
109
104
|
|
|
110
105
|
```javascript
|
|
111
|
-
//
|
|
112
|
-
await testdriver.
|
|
113
|
-
redraw: { enabled: true },
|
|
114
|
-
});
|
|
106
|
+
// Wait for this key press even though redraw is off for the client
|
|
107
|
+
await testdriver.pressKeys(['enter'], { redraw: { enabled: true } });
|
|
115
108
|
|
|
116
|
-
//
|
|
117
|
-
await testdriver.
|
|
118
|
-
redraw: false,
|
|
119
|
-
});
|
|
109
|
+
// Skip the wait for a click you know changes nothing on screen
|
|
110
|
+
await testdriver.click({ x: 640, y: 360, redraw: { enabled: false } });
|
|
120
111
|
```
|
|
121
112
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
When `networkMonitor` is enabled, the system also monitors sandbox network traffic:
|
|
113
|
+
This works on `testdriver.click()`, `hover()`, `type()`, `pressKeys()`, `scroll()`, and `focusApplication()`.
|
|
125
114
|
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
- Calculates z-scores for both RX and TX byte rates
|
|
129
|
-
- Network is **settled** when both RX and TX z-scores are negative (traffic is below average)
|
|
130
|
-
- Has a **10-second timeout** for network polling
|
|
131
|
-
- Non-critical: network errors are logged but never throw
|
|
115
|
+
- Pass an object. A per-command `redraw: true` or `redraw: false` is ignored.
|
|
116
|
+
- Element methods such as `element.click()` don't take options. They always use the client's setting.
|
|
132
117
|
|
|
133
|
-
|
|
118
|
+
## Watch it work
|
|
134
119
|
|
|
135
|
-
|
|
120
|
+
Redraw emits two events on the client's [event emitter](/events#redraw-events):
|
|
136
121
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
| Event | Description |
|
|
140
|
-
|---|---|
|
|
141
|
-
| `redraw:status` | Emitted on each poll with current screen diff, network stats, and timeout info |
|
|
142
|
-
| `redraw:complete` | Emitted when redraw resolves (settled or timed out) |
|
|
122
|
+
- `redraw:status` on every check, with the current screen and network state.
|
|
123
|
+
- `redraw:complete` when the wait ends, with `isTimeout` and `timeElapsed`.
|
|
143
124
|
|
|
144
125
|
```javascript
|
|
145
|
-
testdriver.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
console.log(`Timeout: ${status.timeout.text}`);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
testdriver.emitter.on('redraw:complete', (result) => {
|
|
152
|
-
if (result.isTimeout) {
|
|
153
|
-
console.warn(`Redraw timed out after ${result.timeElapsed}ms`);
|
|
154
|
-
} else {
|
|
155
|
-
console.log(`Screen settled in ${result.timeElapsed}ms`);
|
|
126
|
+
testdriver.getEmitter().on('redraw:complete', ({ isTimeout, timeElapsed }) => {
|
|
127
|
+
if (isTimeout) {
|
|
128
|
+
console.warn(`Screen didn't settle within ${timeElapsed} ms`);
|
|
156
129
|
}
|
|
157
130
|
});
|
|
158
131
|
```
|
|
159
132
|
|
|
160
|
-
## When to
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
-
|
|
166
|
-
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
- You
|
|
173
|
-
|
|
174
|
-
##
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
networkMonitor?: boolean; // Default: false
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
interface RedrawStatusEvent {
|
|
184
|
-
redraw: {
|
|
185
|
-
enabled: boolean;
|
|
186
|
-
settled: boolean;
|
|
187
|
-
hasChangedFromInitial: boolean;
|
|
188
|
-
consecutiveFramesStable: number;
|
|
189
|
-
diffFromInitial: number;
|
|
190
|
-
diffFromLast: number;
|
|
191
|
-
text: string;
|
|
192
|
-
};
|
|
193
|
-
network: {
|
|
194
|
-
enabled: boolean;
|
|
195
|
-
settled: boolean;
|
|
196
|
-
rxBytes: number;
|
|
197
|
-
txBytes: number;
|
|
198
|
-
text: string;
|
|
199
|
-
};
|
|
200
|
-
timeout: {
|
|
201
|
-
isTimeout: boolean;
|
|
202
|
-
elapsed: number;
|
|
203
|
-
max: number;
|
|
204
|
-
text: string;
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
interface RedrawCompleteEvent {
|
|
209
|
-
screenSettled: boolean;
|
|
210
|
-
hasChangedFromInitial: boolean;
|
|
211
|
-
consecutiveFramesStable: number;
|
|
212
|
-
networkSettled: boolean;
|
|
213
|
-
isTimeout: boolean;
|
|
214
|
-
timeElapsed: number;
|
|
215
|
-
}
|
|
216
|
-
```
|
|
133
|
+
## When to use it
|
|
134
|
+
|
|
135
|
+
Turn redraw on when:
|
|
136
|
+
|
|
137
|
+
- Clicks open pages, modals, or menus that animate in.
|
|
138
|
+
- Scrolling loads more content.
|
|
139
|
+
- Typing triggers autocomplete or validation messages.
|
|
140
|
+
|
|
141
|
+
Leave it off when:
|
|
142
|
+
|
|
143
|
+
- Your tests already pass reliably without it. Each action takes longer with it on.
|
|
144
|
+
- Many actions don't visibly change the screen.
|
|
145
|
+
- You already wait with `find()` and a `timeout`, which keeps looking until the element appears.
|
|
146
|
+
|
|
147
|
+
## Related
|
|
148
|
+
|
|
149
|
+
- [Options](/options#redraw-detection): every client option
|
|
150
|
+
- [Events](/events): the full list of events
|
|
151
|
+
- [wait()](/wait): pause for a fixed time
|
|
152
|
+
- [Locate elements](/locating-elements): wait for an element to appear with `find()`
|