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.
Files changed (45) hide show
  1. package/.github/copilot-instructions.md +1 -1
  2. package/.github/skills/testdriver:performing-actions/SKILL.md +3 -0
  3. package/.github/skills/testdriver:waiting-for-elements/SKILL.md +16 -0
  4. package/CHANGELOG.md +4 -0
  5. package/agent/events.js +7 -0
  6. package/agent/index.js +24 -17
  7. package/agent/lib/sandbox.js +703 -428
  8. package/agent/lib/system.js +70 -1
  9. package/ai/agents/testdriver.md +1 -1
  10. package/ai/skills/testdriver:performing-actions/SKILL.md +3 -0
  11. package/ai/skills/testdriver:testdriver/SKILL.md +1 -1
  12. package/ai/skills/testdriver:waiting-for-elements/SKILL.md +16 -0
  13. package/docs/_data/examples-manifest.json +68 -68
  14. package/docs/guide/best-practices-polling.mdx +25 -5
  15. package/docs/v7/examples/ai.mdx +1 -1
  16. package/docs/v7/examples/assert.mdx +1 -1
  17. package/docs/v7/examples/chrome-extension.mdx +1 -1
  18. package/docs/v7/examples/drag-and-drop.mdx +1 -1
  19. package/docs/v7/examples/element-not-found.mdx +1 -1
  20. package/docs/v7/examples/hover-image.mdx +1 -1
  21. package/docs/v7/examples/hover-text.mdx +1 -1
  22. package/docs/v7/examples/installer.mdx +1 -1
  23. package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
  24. package/docs/v7/examples/match-image.mdx +1 -1
  25. package/docs/v7/examples/press-keys.mdx +1 -1
  26. package/docs/v7/examples/scroll-keyboard.mdx +1 -1
  27. package/docs/v7/examples/scroll-until-image.mdx +1 -1
  28. package/docs/v7/examples/scroll-until-text.mdx +1 -1
  29. package/docs/v7/examples/scroll.mdx +1 -1
  30. package/docs/v7/examples/type.mdx +1 -1
  31. package/docs/v7/examples/windows-installer.mdx +1 -1
  32. package/docs/v7/performing-actions.mdx +3 -0
  33. package/docs/v7/wait.mdx +52 -0
  34. package/docs/v7/waiting-for-elements.mdx +18 -0
  35. package/examples/chrome-extension.test.mjs +2 -0
  36. package/examples/no-provision.test.mjs +2 -0
  37. package/lib/vitest/hooks.mjs +9 -0
  38. package/lib/vitest/setup-aws.mjs +1 -0
  39. package/manual/packer-hover-image.test.mjs +176 -0
  40. package/package.json +2 -1
  41. package/sdk.d.ts +14 -2
  42. package/sdk.js +10 -0
  43. package/setup/aws/cloudformation.yaml +1 -8
  44. package/setup/aws/spawn-runner.sh +2 -37
  45. 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. **⚠️ NEVER USE `.wait()`** - Do NOT use any `.wait()` method. Instead, use `find()` with a `timeout` option to poll for elements, or use `assert()` / `check()` to verify state. Explicit waits are flaky and slow.
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
@@ -1,3 +1,7 @@
1
+ ## [7.4.5](https://github.com/testdriverai/testdriverai/compare/v7.3.43...v7.4.5) (2026-02-27)
2
+
3
+
4
+
1
5
  ## [7.3.44](https://github.com/testdriverai/testdriverai/compare/v7.3.43...v7.3.44) (2026-02-26)
2
6
 
3
7
 
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
- // We don't have resiliency/retries baked in, so let's at least give it 1 attempt
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
- let instance = await this.connectToSandboxDirect(
1766
- this.sandboxId,
1767
- true, // always persist by default
1768
- this.keepAlive, // pass keepAlive TTL
1769
- );
1770
- this.instance = instance;
1771
- await this.renderSandbox(instance, headless);
1772
- await this.runLifecycle("provision");
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