testdriverai 7.0.0 → 7.1.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 (112) hide show
  1. package/AGENTS.md +550 -0
  2. package/CODEOWNERS +0 -1
  3. package/README.md +126 -0
  4. package/agent/index.js +43 -18
  5. package/agent/lib/commands.js +794 -135
  6. package/agent/lib/redraw.js +124 -39
  7. package/agent/lib/sandbox.js +10 -1
  8. package/agent/lib/sdk.js +21 -0
  9. package/docs/MIGRATION.md +425 -0
  10. package/docs/PRESETS.md +210 -0
  11. package/docs/docs.json +91 -37
  12. package/docs/guide/best-practices-polling.mdx +154 -0
  13. package/docs/v7/api/dashcam.mdx +497 -0
  14. package/docs/v7/api/doubleClick.mdx +102 -0
  15. package/docs/v7/api/mouseDown.mdx +161 -0
  16. package/docs/v7/api/mouseUp.mdx +164 -0
  17. package/docs/v7/api/rightClick.mdx +123 -0
  18. package/docs/v7/getting-started/configuration.mdx +380 -0
  19. package/docs/v7/getting-started/quickstart.mdx +273 -140
  20. package/docs/v7/guides/best-practices.mdx +486 -0
  21. package/docs/v7/guides/caching-ai.mdx +215 -0
  22. package/docs/v7/guides/caching-selectors.mdx +292 -0
  23. package/docs/v7/guides/caching.mdx +366 -0
  24. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  25. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  26. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  27. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  28. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  29. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  30. package/docs/v7/guides/debugging.mdx +349 -0
  31. package/docs/v7/guides/faq.mdx +393 -0
  32. package/docs/v7/guides/performance.mdx +517 -0
  33. package/docs/v7/guides/troubleshooting.mdx +526 -0
  34. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  35. package/docs/v7/guides/vitest.mdx +535 -0
  36. package/docs/v7/platforms/linux.mdx +308 -0
  37. package/docs/v7/platforms/macos.mdx +433 -0
  38. package/docs/v7/platforms/windows.mdx +430 -0
  39. package/docs/v7/presets/chrome-extension.mdx +223 -0
  40. package/docs/v7/presets/chrome.mdx +287 -0
  41. package/docs/v7/presets/electron.mdx +435 -0
  42. package/docs/v7/presets/vscode.mdx +398 -0
  43. package/docs/v7/presets/webapp.mdx +396 -0
  44. package/docs/v7/progressive-apis/CORE.md +459 -0
  45. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  46. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  47. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  48. package/interfaces/vitest-plugin.mjs +186 -100
  49. package/package.json +12 -1
  50. package/sdk.d.ts +335 -42
  51. package/sdk.js +756 -95
  52. package/src/core/Dashcam.js +469 -0
  53. package/src/core/index.d.ts +150 -0
  54. package/src/core/index.js +12 -0
  55. package/src/presets/index.mjs +331 -0
  56. package/src/vitest/extended.mjs +108 -0
  57. package/src/vitest/hooks.d.ts +119 -0
  58. package/src/vitest/hooks.mjs +298 -0
  59. package/src/vitest/index.mjs +64 -0
  60. package/src/vitest/lifecycle.mjs +277 -0
  61. package/src/vitest/utils.mjs +150 -0
  62. package/test/dashcam.test.js +137 -0
  63. package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
  64. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  65. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  66. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
  67. package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
  68. package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
  69. package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
  70. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
  71. package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
  72. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
  73. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  74. package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
  75. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
  76. package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
  77. package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
  78. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  79. package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
  80. package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
  81. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
  82. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
  83. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
  84. package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
  85. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
  86. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  87. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  88. package/testdriver/acceptance-sdk/type.test.mjs +19 -58
  89. package/vitest.config.mjs +1 -0
  90. package/.vscode/mcp.json +0 -9
  91. package/MIGRATION.md +0 -389
  92. package/PLUGIN_MIGRATION.md +0 -222
  93. package/PROMPT_CACHE.md +0 -200
  94. package/SDK_LOGGING.md +0 -222
  95. package/SDK_MIGRATION.md +0 -474
  96. package/SDK_README.md +0 -1122
  97. package/debug-screenshot-1763401388589.png +0 -0
  98. package/examples/run-tests-with-recording.sh +0 -70
  99. package/examples/screenshot-example.js +0 -63
  100. package/examples/sdk-awesome-logs-demo.js +0 -177
  101. package/examples/sdk-cache-thresholds.js +0 -96
  102. package/examples/sdk-element-properties.js +0 -155
  103. package/examples/sdk-simple-example.js +0 -65
  104. package/examples/test-recording-example.test.js +0 -166
  105. package/mcp-server/AI_GUIDELINES.md +0 -57
  106. package/test-find-api.js +0 -73
  107. package/test-prompt-cache.js +0 -96
  108. package/test-sandbox-render.js +0 -28
  109. package/test-sdk-methods.js +0 -15
  110. package/test-sdk-refactor.js +0 -53
  111. package/test-stack-trace.mjs +0 -57
  112. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
package/agent/index.js CHANGED
@@ -109,8 +109,8 @@ class TestDriverAgent extends EventEmitter2 {
109
109
  // Create analytics instance with this agent's emitter, config, and session
110
110
  this.analytics = createAnalytics(this.emitter, this.config, this.session);
111
111
 
112
- // Create sandbox instance with this agent's emitter and analytics
113
- this.sandbox = createSandbox(this.emitter, this.analytics);
112
+ // Create sandbox instance with this agent's emitter, analytics, and session
113
+ this.sandbox = createSandbox(this.emitter, this.analytics, this.session);
114
114
 
115
115
  // Set the OS for the sandbox to use
116
116
  this.sandbox.os = this.sandboxOs;
@@ -127,6 +127,7 @@ class TestDriverAgent extends EventEmitter2 {
127
127
  this.session,
128
128
  () => this.sourceMapper.currentFilePath || this.thisFile,
129
129
  this.cliArgs.options.redrawThreshold,
130
+ null, // getDashcamElapsedTime - will be set by SDK when dashcam is available
130
131
  );
131
132
  this.commands = commandsResult.commands;
132
133
  this.redraw = commandsResult.redraw;
@@ -1710,12 +1711,28 @@ ${regression}
1710
1711
  this.emitter.emit(events.log.log, `${inputFile} (end)`);
1711
1712
  }
1712
1713
 
1714
+ // Returns the path to the sandbox file (project-local first, then global)
1715
+ getSandboxFilePath(preferProjectLocal = true) {
1716
+ const projectLocalFile = path.join(process.cwd(), ".testdriver-sandbox.json");
1717
+ const globalFile = path.join(os.homedir(), ".testdriverai-last-sandbox");
1718
+
1719
+ if (preferProjectLocal) {
1720
+ // For reading: check project-local first, then global
1721
+ if (fs.existsSync(projectLocalFile)) {
1722
+ return projectLocalFile;
1723
+ }
1724
+ if (fs.existsSync(globalFile)) {
1725
+ return globalFile;
1726
+ }
1727
+ // For writing: default to project-local
1728
+ return projectLocalFile;
1729
+ }
1730
+ return globalFile;
1731
+ }
1732
+
1713
1733
  // Returns sandboxId to use (either from file if recent, or null)
1714
1734
  getRecentSandboxId() {
1715
- const lastSandboxFile = path.join(
1716
- os.homedir(),
1717
- ".testdriverai-last-sandbox",
1718
- );
1735
+ const lastSandboxFile = this.getSandboxFilePath(true);
1719
1736
 
1720
1737
  if (fs.existsSync(lastSandboxFile)) {
1721
1738
  try {
@@ -1761,10 +1778,8 @@ ${regression}
1761
1778
  }
1762
1779
 
1763
1780
  saveLastSandboxId(sandboxId, osType = "linux") {
1764
- const lastSandboxFile = path.join(
1765
- os.homedir(),
1766
- ".testdriverai-last-sandbox",
1767
- );
1781
+ // Save to project-local .testdriver-sandbox.json
1782
+ const projectLocalFile = path.join(process.cwd(), ".testdriver-sandbox.json");
1768
1783
  try {
1769
1784
  const sandboxInfo = {
1770
1785
  sandboxId: sandboxId,
@@ -1773,7 +1788,7 @@ ${regression}
1773
1788
  instanceType: this.sandboxInstance || null,
1774
1789
  timestamp: new Date().toISOString(),
1775
1790
  };
1776
- fs.writeFileSync(lastSandboxFile, JSON.stringify(sandboxInfo), {
1791
+ fs.writeFileSync(projectLocalFile, JSON.stringify(sandboxInfo, null, 2), {
1777
1792
  encoding: "utf-8",
1778
1793
  });
1779
1794
  } catch {
@@ -1782,13 +1797,16 @@ ${regression}
1782
1797
  }
1783
1798
 
1784
1799
  clearRecentSandboxId() {
1785
- const lastSandboxFile = path.join(
1786
- os.homedir(),
1787
- ".testdriverai-last-sandbox",
1788
- );
1800
+ // Clear project-local file first, then global
1801
+ const projectLocalFile = path.join(process.cwd(), ".testdriver-sandbox.json");
1802
+ const globalFile = path.join(os.homedir(), ".testdriverai-last-sandbox");
1803
+
1789
1804
  try {
1790
- if (fs.existsSync(lastSandboxFile)) {
1791
- fs.unlinkSync(lastSandboxFile);
1805
+ if (fs.existsSync(projectLocalFile)) {
1806
+ fs.unlinkSync(projectLocalFile);
1807
+ }
1808
+ if (fs.existsSync(globalFile)) {
1809
+ fs.unlinkSync(globalFile);
1792
1810
  }
1793
1811
  } catch {
1794
1812
  // ignore errors
@@ -1844,6 +1862,9 @@ ${regression}
1844
1862
  await this.connectToSandboxService();
1845
1863
 
1846
1864
  const recentId = createNew ? null : this.getRecentSandboxId();
1865
+
1866
+ // Track whether we reconnected to an existing sandbox or created a new one
1867
+ this.isReconnected = false;
1847
1868
 
1848
1869
  // Set sandbox ID for reconnection (only if not creating new and recent ID exists)
1849
1870
  if (this.ip) {
@@ -1857,6 +1878,7 @@ ${regression}
1857
1878
  this.emitter.emit(events.sandbox.connected);
1858
1879
 
1859
1880
  this.instance = instance.instance;
1881
+ this.isReconnected = false; // Direct IP is considered new
1860
1882
  await this.renderSandbox(this.instance, headless);
1861
1883
  await this.newSession();
1862
1884
  await this.runLifecycle("provision");
@@ -1877,6 +1899,7 @@ ${regression}
1877
1899
  );
1878
1900
 
1879
1901
  this.instance = instance;
1902
+ this.isReconnected = true; // Successfully reconnected to existing sandbox
1880
1903
 
1881
1904
  await this.renderSandbox(instance, headless);
1882
1905
  await this.newSession();
@@ -1909,6 +1932,7 @@ ${regression}
1909
1932
  );
1910
1933
 
1911
1934
  this.instance = instance;
1935
+ this.isReconnected = true; // Successfully reconnected to existing sandbox
1912
1936
 
1913
1937
  await this.renderSandbox(instance, headless);
1914
1938
  await this.newSession();
@@ -1925,9 +1949,10 @@ ${regression}
1925
1949
 
1926
1950
  // Create new sandbox (either because createNew is true, or no existing sandbox to connect to)
1927
1951
  if (!this.instance) {
1952
+ this.isReconnected = false; // Creating new sandbox
1928
1953
  this.emitter.emit(
1929
1954
  events.log.narration,
1930
- theme.dim(`creating new sandbox (can take up to 2 minutes)...`),
1955
+ theme.dim(`creating new sandbox...`),
1931
1956
  );
1932
1957
  // We don't have resiliency/retries baked in, so let's at least give it 1 attempt
1933
1958
  // to see if that fixes the issue.