testdriverai 7.4.4 → 7.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +1 -1
- package/.github/skills/testdriver:performing-actions/SKILL.md +3 -0
- package/.github/skills/testdriver:waiting-for-elements/SKILL.md +16 -0
- package/CHANGELOG.md +4 -0
- package/agent/events.js +7 -0
- package/agent/index.js +24 -17
- package/agent/lib/sandbox.js +703 -428
- package/agent/lib/system.js +70 -1
- package/ai/agents/testdriver.md +1 -1
- package/ai/skills/testdriver:performing-actions/SKILL.md +3 -0
- package/ai/skills/testdriver:testdriver/SKILL.md +1 -1
- package/ai/skills/testdriver:waiting-for-elements/SKILL.md +16 -0
- package/docs/_data/examples-manifest.json +68 -68
- package/docs/guide/best-practices-polling.mdx +25 -5
- package/docs/v7/examples/ai.mdx +1 -1
- package/docs/v7/examples/assert.mdx +1 -1
- package/docs/v7/examples/chrome-extension.mdx +1 -1
- package/docs/v7/examples/drag-and-drop.mdx +1 -1
- package/docs/v7/examples/element-not-found.mdx +1 -1
- package/docs/v7/examples/hover-image.mdx +1 -1
- package/docs/v7/examples/hover-text.mdx +1 -1
- package/docs/v7/examples/installer.mdx +1 -1
- package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
- package/docs/v7/examples/match-image.mdx +1 -1
- package/docs/v7/examples/press-keys.mdx +1 -1
- package/docs/v7/examples/scroll-keyboard.mdx +1 -1
- package/docs/v7/examples/scroll-until-image.mdx +1 -1
- package/docs/v7/examples/scroll-until-text.mdx +1 -1
- package/docs/v7/examples/scroll.mdx +1 -1
- package/docs/v7/examples/type.mdx +1 -1
- package/docs/v7/examples/windows-installer.mdx +1 -1
- package/docs/v7/performing-actions.mdx +3 -0
- package/docs/v7/wait.mdx +52 -0
- package/docs/v7/waiting-for-elements.mdx +18 -0
- package/examples/chrome-extension.test.mjs +2 -0
- package/examples/no-provision.test.mjs +2 -0
- package/lib/vitest/hooks.mjs +9 -0
- package/lib/vitest/setup-aws.mjs +1 -0
- package/manual/packer-hover-image.test.mjs +176 -0
- package/package.json +2 -1
- package/sdk.d.ts +14 -2
- package/sdk.js +10 -0
- package/setup/aws/cloudformation.yaml +1 -8
- package/setup/aws/spawn-runner.sh +2 -37
- package/vitest.config.mjs +1 -1
|
@@ -670,7 +670,7 @@ await testdriver.screenshot(1, false, true);
|
|
|
670
670
|
3. **⚠️ SHARE THE TEST REPORT URL** - After EVERY test run, find `TESTDRIVER_RUN_URL=https://console.testdriver.ai/runs/...` in the output and share it with the user. This is CRITICAL - users need to view the recording to understand what happened.
|
|
671
671
|
3. **Screenshots are automatic** - TestDriver captures screenshots before/after every command by default. Each screenshot filename includes the line number (e.g., `001-click-before-L42-submit-button.png`) making it easy to trace issues.
|
|
672
672
|
4. **⚠️ USE SCREENSHOT VIEWING FOR DEBUGGING** - When tests fail, use `list_local_screenshots` and `view_local_screenshot` MCP commands to see exactly what the UI looked like. The filenames tell you which line of code triggered each screenshot.
|
|
673
|
-
5.
|
|
673
|
+
5. **Use `wait()` for simple delays** - Use `await testdriver.wait(ms)` when you need a pause (e.g., after actions, for animations). For waiting for specific elements, prefer `find()` with a `timeout` option.
|
|
674
674
|
6. **Use MCP tools for development** - Build tests interactively with visual feedback
|
|
675
675
|
7. **Always check `sdk.d.ts`** for method signatures and types when debugging generated tests
|
|
676
676
|
8. **Look at test samples** in `node_modules/testdriverai/test` for working examples
|
|
@@ -29,6 +29,9 @@ await testdriver.find('dropdown menu').hover();
|
|
|
29
29
|
await testdriver.scroll('down', 500);
|
|
30
30
|
await testdriver.scrollUntilText('Footer content');
|
|
31
31
|
|
|
32
|
+
// Waiting
|
|
33
|
+
await testdriver.wait(2000); // Wait 2 seconds for animation/state change
|
|
34
|
+
|
|
32
35
|
// Extracting information from screen
|
|
33
36
|
const price = await testdriver.extract('the total price');
|
|
34
37
|
const orderNumber = await testdriver.extract('the order confirmation number');
|
|
@@ -70,3 +70,19 @@ const testdriver = TestDriver(context, {
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
```
|
|
73
|
+
|
|
74
|
+
## Simple Delays with `wait()`
|
|
75
|
+
|
|
76
|
+
For simple pauses — waiting for animations, transitions, or state changes after an action — use `wait()`:
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// Wait for an animation to complete
|
|
80
|
+
await testdriver.find('menu toggle').click();
|
|
81
|
+
await testdriver.wait(2000);
|
|
82
|
+
|
|
83
|
+
// Wait for a page transition to settle
|
|
84
|
+
await testdriver.find('next page button').click();
|
|
85
|
+
await testdriver.wait(1000);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
|
package/CHANGELOG.md
CHANGED
package/agent/events.js
CHANGED
|
@@ -101,11 +101,18 @@ const events = {
|
|
|
101
101
|
sent: "sandbox:sent",
|
|
102
102
|
received: "sandbox:received",
|
|
103
103
|
progress: "sandbox:progress",
|
|
104
|
+
file: "sandbox:file",
|
|
104
105
|
},
|
|
105
106
|
redraw: {
|
|
106
107
|
status: "redraw:status",
|
|
107
108
|
complete: "redraw:complete",
|
|
108
109
|
},
|
|
110
|
+
exec: {
|
|
111
|
+
output: "exec:output",
|
|
112
|
+
},
|
|
113
|
+
runner: {
|
|
114
|
+
log: "runner:log",
|
|
115
|
+
},
|
|
109
116
|
exit: "exit",
|
|
110
117
|
};
|
|
111
118
|
|
package/agent/index.js
CHANGED
|
@@ -1686,6 +1686,7 @@ ${regression}
|
|
|
1686
1686
|
resolution: this.config.TD_RESOLUTION,
|
|
1687
1687
|
ci: this.config.CI,
|
|
1688
1688
|
ip: this.ip,
|
|
1689
|
+
instanceId: this.instanceId || undefined,
|
|
1689
1690
|
});
|
|
1690
1691
|
|
|
1691
1692
|
// Store connection params for reconnection
|
|
@@ -1748,28 +1749,34 @@ ${regression}
|
|
|
1748
1749
|
" " +
|
|
1749
1750
|
theme.cyan(`new sandbox...`),
|
|
1750
1751
|
);
|
|
1751
|
-
|
|
1752
|
-
// to see if that fixes the issue.
|
|
1753
|
-
let newSandbox = await this.createNewSandbox().catch(() => {
|
|
1754
|
-
this.emitter.emit(
|
|
1755
|
-
events.log.narration,
|
|
1756
|
-
theme.dim(`double-checking sandbox availability`),
|
|
1757
|
-
);
|
|
1758
|
-
return this.createNewSandbox();
|
|
1759
|
-
});
|
|
1752
|
+
let newSandbox = await this.createNewSandbox();
|
|
1760
1753
|
|
|
1761
1754
|
// Extract the sandbox ID from the newly created sandbox
|
|
1762
1755
|
this.sandboxId =
|
|
1763
1756
|
newSandbox?.sandbox?.sandboxId || newSandbox?.sandbox?.instanceId;
|
|
1764
1757
|
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
this.
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1758
|
+
// E2B sandboxes return a url directly from create — no separate
|
|
1759
|
+
// connect step needed (the API proxies commands via Ably).
|
|
1760
|
+
if (newSandbox?.sandbox?.url) {
|
|
1761
|
+
this.sandbox.setConnectionParams({
|
|
1762
|
+
sandboxId: this.sandboxId,
|
|
1763
|
+
persist: true,
|
|
1764
|
+
keepAlive: this.keepAlive,
|
|
1765
|
+
});
|
|
1766
|
+
this.emitter.emit(events.sandbox.connected);
|
|
1767
|
+
this.instance = newSandbox.sandbox;
|
|
1768
|
+
await this.renderSandbox(this.instance, headless);
|
|
1769
|
+
await this.runLifecycle("provision");
|
|
1770
|
+
} else {
|
|
1771
|
+
let instance = await this.connectToSandboxDirect(
|
|
1772
|
+
this.sandboxId,
|
|
1773
|
+
true, // always persist by default
|
|
1774
|
+
this.keepAlive, // pass keepAlive TTL
|
|
1775
|
+
);
|
|
1776
|
+
this.instance = instance;
|
|
1777
|
+
await this.renderSandbox(instance, headless);
|
|
1778
|
+
await this.runLifecycle("provision");
|
|
1779
|
+
}
|
|
1773
1780
|
}
|
|
1774
1781
|
}
|
|
1775
1782
|
|