@testdriverai/agent 7.11.229-canary → 7.11.232-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.
Files changed (100) hide show
  1. package/docs/_data/examples-manifest.json +16 -16
  2. package/docs/_scripts/generate-examples.js +38 -45
  3. package/docs/agent.mdx +174 -93
  4. package/docs/assert.mdx +73 -269
  5. package/docs/aws-setup.mdx +196 -314
  6. package/docs/bring-your-own-machine.mdx +139 -206
  7. package/docs/cache.mdx +144 -151
  8. package/docs/caching.mdx +99 -89
  9. package/docs/captcha.mdx +126 -111
  10. package/docs/ci-cd.mdx +154 -543
  11. package/docs/click.mdx +74 -229
  12. package/docs/client.mdx +177 -231
  13. package/docs/copilot/auto-healing.mdx +86 -370
  14. package/docs/copilot/running-tests.mdx +121 -930
  15. package/docs/customizing-devices.mdx +74 -251
  16. package/docs/dashcam.mdx +72 -405
  17. package/docs/debugging-with-screenshots.mdx +105 -371
  18. package/docs/docs.json +79 -22
  19. package/docs/double-click.mdx +48 -68
  20. package/docs/errors.mdx +102 -176
  21. package/docs/events.mdx +170 -327
  22. package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
  23. package/docs/examples/assert.mdx +28 -41
  24. package/docs/examples/click-button.mdx +71 -0
  25. package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
  26. package/docs/examples/element-not-found.mdx +27 -26
  27. package/docs/examples/findall-coffee-icons.mdx +28 -32
  28. package/docs/examples/installer.mdx +61 -25
  29. package/docs/examples/launch-vscode-linux.mdx +28 -51
  30. package/docs/examples/navigate-and-scroll.mdx +82 -0
  31. package/docs/examples/parse.mdx +24 -28
  32. package/docs/examples/press-keys.mdx +28 -25
  33. package/docs/examples/scroll.mdx +25 -27
  34. package/docs/examples/type.mdx +26 -21
  35. package/docs/exec.mdx +92 -256
  36. package/docs/extract.mdx +69 -170
  37. package/docs/find.mdx +140 -736
  38. package/docs/focus-application.mdx +69 -246
  39. package/docs/generating-tests.mdx +103 -137
  40. package/docs/guide/best-practices-polling.mdx +65 -141
  41. package/docs/hosted.mdx +80 -144
  42. package/docs/hover.mdx +62 -235
  43. package/docs/locating-elements.mdx +74 -369
  44. package/docs/making-assertions.mdx +116 -74
  45. package/docs/mcp-setup.mdx +80 -63
  46. package/docs/mouse-down.mdx +48 -125
  47. package/docs/mouse-up.mdx +47 -129
  48. package/docs/options.mdx +75 -48
  49. package/docs/parse.mdx +95 -184
  50. package/docs/performing-actions.mdx +104 -94
  51. package/docs/press-keys.mdx +59 -299
  52. package/docs/provision.mdx +137 -182
  53. package/docs/quickstart-claude.mdx +85 -0
  54. package/docs/quickstart-github.mdx +62 -32
  55. package/docs/quickstart-manual.mdx +60 -33
  56. package/docs/quickstart-vscode.mdx +97 -0
  57. package/docs/quickstart.mdx +26 -9
  58. package/docs/redraw.mdx +101 -165
  59. package/docs/reusable-code.mdx +97 -200
  60. package/docs/right-click.mdx +47 -89
  61. package/docs/screenshot.mdx +47 -201
  62. package/docs/screenshots.mdx +87 -137
  63. package/docs/scroll.mdx +71 -154
  64. package/docs/secrets.mdx +96 -91
  65. package/docs/self-hosted.mdx +83 -142
  66. package/docs/snippets/enterprise.mdx +15 -0
  67. package/docs/styles.css +68 -0
  68. package/docs/test-results-json.mdx +167 -204
  69. package/docs/type.mdx +56 -304
  70. package/docs/variables.mdx +121 -81
  71. package/docs/wait.mdx +33 -31
  72. package/docs/what-is-testdriver.mdx +80 -32
  73. package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
  74. package/examples/assert.test.mjs +3 -20
  75. package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
  76. package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
  77. package/examples/element-not-found.test.mjs +3 -5
  78. package/examples/findall-coffee-icons.test.mjs +3 -3
  79. package/examples/installer.test.mjs +1 -1
  80. package/examples/launch-vscode-linux.test.mjs +6 -33
  81. package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
  82. package/examples/parse.test.mjs +1 -2
  83. package/examples/press-keys.test.mjs +4 -4
  84. package/examples/scroll.test.mjs +3 -6
  85. package/examples/type.test.mjs +5 -2
  86. package/lib/provision.js +6 -2
  87. package/package.json +1 -1
  88. package/sdk.d.ts +4 -2
  89. package/sdk.js +1 -1
  90. package/docs/claude-mcp-plugin.mdx +0 -244
  91. package/docs/elements.mdx +0 -606
  92. package/docs/examples/ai.mdx +0 -78
  93. package/docs/examples/captcha-api.mdx +0 -92
  94. package/docs/examples/chrome-extension.mdx +0 -156
  95. package/docs/examples/drag-and-drop.mdx +0 -100
  96. package/docs/examples/formatted-logging.mdx +0 -74
  97. package/docs/examples/hover-text.mdx +0 -70
  98. package/docs/examples/match-image.mdx +0 -97
  99. package/docs/examples/scroll-keyboard.mdx +0 -80
  100. package/docs/examples/scroll-until-text.mdx +0 -109
@@ -1,28 +1,49 @@
1
1
  ---
2
- title: "Manual"
2
+ title: "Set up a project"
3
3
  sidebarTitle: "Setting up your workspace"
4
- description: "Add TestDriver to an existing project by hand."
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 an existing project without the `init` scaffold. This is useful when you already have a Vitest setup or want full control over each file.
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
- If you only want to drive TestDriver from chat, [MCP Setup](/mcp-setup) is a single URL with nothing to install.
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="Get an API key">
16
-
17
- <Card
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 is not committed.
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
- <Note>
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 (or add these settings to an existing one):
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
- - `TestDriver()` reporter uploads results, recordings, and screenshots to the console.
69
- - `setupFiles` registers the hooks that connect each test to a sandbox and clean it up.
70
- - Without `hookTimeout`, cleanup fails at Vitest's default 10-second limit.
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 project does not have `"type": "module"` in `package.json`, name the file `search.test.mjs` instead.
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. When the run finishes, open the `TESTDRIVER_RUN_URL` printed at the end of the output to see the recording and step-by-step screenshots.
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
- ## Optional: AI client setup
137
+ ## Connect an AI assistant
117
138
 
118
- If you want to write tests with an AI assistant, connect the TestDriver agent and MCP server. You can do this without re-scaffolding the project:
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
- See [MCP Setup](/mcp-setup) for the configuration of each client.
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="Walkthrough" icon="map" href="/provision" arrow horizontal>
130
- Provision apps, locate elements, perform actions, and make assertions.
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="github" href="/ci-cd" arrow horizontal>
133
- Run tests on every pull request with GitHub Actions or another provider.
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>
@@ -1,22 +1,39 @@
1
1
  ---
2
- title: "Quick Start"
2
+ title: "Quickstart"
3
3
  sidebarTitle: "Quickstart"
4
- description: "Run your first computer-use test in minutes."
4
+ description: "Start with TestDriver from GitHub, Claude Code, VS Code, Cursor, any MCP client, or your own project."
5
5
  icon: "rocket"
6
+ mode: "wide"
6
7
  ---
7
8
 
8
- TestDriver writes and runs computer-use tests for web apps, desktop apps, and browser extensions. Tests describe what a user sees and does in plain English, and run on real machines in the cloud. Pick the path that fits how you work:
9
+ TestDriver writes and runs end-to-end tests for web apps, desktop apps, and browser extensions.
10
+
11
+ Each test describes what a user sees and does in plain language. It runs on a real machine in the cloud.
12
+
13
+ Choose where you want to start:
9
14
 
10
15
  <CardGroup cols={1}>
11
16
  <Card title="Add to GitHub" icon="github" href="/quickstart-github" arrow horizontal>
12
- No install. Mention `@testdriverai` in a PR or issue and it writes, runs, and commits tests for you.
17
+ An AI code reviewer that tests every pull request in a real sandbox.
18
+ </Card>
19
+ <Card title="Claude Code" icon="terminal" href="/quickstart-claude" arrow horizontal>
20
+ Install the plugin to write and run tests from Claude Code.
13
21
  </Card>
14
- <Card title="MCP Setup" icon="plug" href="/mcp-setup" arrow horizontal>
15
- Add one URL to Claude, Cursor, VS Code, ChatGPT, or any MCP client. No install, no API key.
22
+ <Card title="VS Code & Cursor" icon="code" href="/quickstart-vscode" arrow horizontal>
23
+ Install the extension to write tests and watch them run live.
16
24
  </Card>
17
- <Card title="Manual" icon="wrench" href="/quickstart-manual" arrow horizontal>
18
- Add TestDriver to an existing Vitest project file by file.
25
+ <Card title="Connect your AI client" icon="plug" href="/mcp-setup" arrow horizontal>
26
+ Add one URL to any MCP client, such as Claude or ChatGPT.
27
+ </Card>
28
+ <Card title="Set up a project" icon="wrench" href="/quickstart-manual" arrow horizontal>
29
+ Write and run Vitest tests in your own repository.
19
30
  </Card>
20
31
  </CardGroup>
21
32
 
22
- <Tip><a href="https://discord.com/invite/cWDFW8DzPm" target="_blank" rel="noreferrer">Join our Discord</a> if you have questions or get stuck.</Tip>
33
+ Not sure? Start with GitHub. Your next pull request gets a review without any setup.
34
+
35
+ Set up a project when you want to write and run tests yourself.
36
+
37
+ <Tip>
38
+ Questions along the way? Ask in the [TestDriver Discord](https://discord.com/invite/cWDFW8DzPm).
39
+ </Tip>
package/docs/redraw.mdx CHANGED
@@ -1,216 +1,152 @@
1
1
  ---
2
- title: "Redraw"
2
+ title: "Wait for the screen to settle"
3
3
  sidebarTitle: "Redraw"
4
- description: "Wait for the screen to stabilize after interactions"
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
- ## Overview
9
+ Redraw detection makes each action wait until the screen has changed and then stopped changing.
10
10
 
11
- The redraw system waits for the screen to become stable after an interaction. Then it continues. It finds when animations, page loads, and network requests are complete. This stops actions on a screen that changes.
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
- <Note>
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
- ## How It Works
17
+ Pass `redraw: true` when you create the client:
18
18
 
19
- Redraw uses a **two-phase detection** method:
19
+ ```javascript tests/search.test.mjs
20
+ import { describe, expect, it } from 'vitest';
21
+ import { TestDriver } from 'testdriverai/vitest/hooks';
20
22
 
21
- 1. **Change Detection**. TestDriver compares the present frame to the first screenshot from after the action. If the pixel diff is more than 0.1%, the screen changed.
22
- 2. **Stability Detection** — TestDriver compares frames that come after each other with z-score analysis. When the diff between frames is less than 0.1%, or the z-score is negative (the present diff is less than the average), the screen is complete.
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
- The screen is **complete** when both phases finish: the screen changed from the first state AND the frames that come after each other are now stable.
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
- ```mermaid
27
- flowchart TD
28
- A[Action performed] --> B{Phase 1: Change Detection\ndiffFromInitial > 0.1%?}
29
- B -- "Yes (screen changed)" --> C{Phase 2: Stability\nz-score < 0 or\ndiffPercent < 0.1%?}
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
- ### Polling
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
- Screen stability uses statistical analysis of the last **10 measurements**:
39
+ ## What it waits for
46
40
 
47
- 1. Calculate the mean and standard deviation of consecutive frame diffs
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
- This approach adapts to the specific animation patterns of your application rather than using a fixed threshold.
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
- ## Per-Command Timeouts
46
+ If the screen doesn't settle in time, the command carries on anyway. It doesn't throw.
54
47
 
55
- Each command type has a specific redraw timeout:
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
- | Command | Timeout | Reason |
58
- |---------|---------|--------|
59
- | `click` | 5000ms | Page navigations, modal openings |
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
- If the timeout is reached before the screen settles, the command continues anyway. The timeout event is available via the `redraw:complete` event.
61
+ ## Wait for network traffic too
68
62
 
69
- ## Configuration
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 = new TestDriver({
75
- // Shorthand: enable/disable
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
- <ParamField path="redraw" type="RedrawConfig | boolean" default={false}>
89
- Redraw configuration. Pass `true`/`false` for shorthand, or an object for fine-grained control.
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={false}>
93
- Enable or disable the redraw system. Default changed to `false` in v7.3.
81
+ <ParamField path="enabled" type="boolean" default="true">
82
+ Whether redraw detection is on when you pass an object.
94
83
  </ParamField>
95
-
96
- <ParamField path="screenRedraw" type="boolean" default={true}>
97
- Enable pixel-diff-based screen change detection. If both `screenRedraw` and `networkMonitor` are `false`, redraw auto-disables.
98
- </ParamField>
99
-
100
- <ParamField path="networkMonitor" type="boolean" default={false}>
101
- Enable network traffic monitoring for settling detection. Monitors WebSocket traffic on the sandbox to detect when network activity subsides.
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
- ### Per-Command Override
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
- Override redraw settings for individual commands:
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
- // Enable redraw for a specific click
112
- await testdriver.find('load more').click({
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
- // Disable redraw for a fast interaction
117
- await testdriver.find('checkbox').click({
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
- ## Network Settling
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
- - Polls for `totalBytesReceived` and `totalBytesSent` from the sandbox
127
- - Keeps the last **60 measurements**
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
- The final settling condition requires **both** screen AND network to be settled (when both are enabled).
118
+ ## Watch it work
134
119
 
135
- ## Events
120
+ Redraw emits two events on the client's [event emitter](/events#redraw-events):
136
121
 
137
- The redraw system emits events through the SDK emitter. See [Events](/events) for the full event reference.
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.emitter.on('redraw:status', (status) => {
146
- console.log(`Screen: ${status.redraw.text}`);
147
- console.log(`Network: ${status.network.text}`);
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 Use Redraw
161
-
162
- **Enable redraw when:**
163
- - Testing single-page applications (SPAs) with route transitions
164
- - Interacting with pages that lazy-load content on scroll
165
- - Clicking buttons that trigger animations or modals
166
- - Testing apps with significant network-driven UI updates
167
-
168
- **Keep redraw disabled when:**
169
- - Tests are already stable without it
170
- - You want faster test execution
171
- - Your application has minimal animations
172
- - You're using explicit waits or assertions instead
173
-
174
- ## Types
175
-
176
- ```typescript
177
- interface RedrawConfig {
178
- enabled?: boolean; // Default: false (since v7.3)
179
- screenRedraw?: boolean; // Default: true
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()`