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.
- package/AGENTS.md +550 -0
- package/CODEOWNERS +0 -1
- package/README.md +126 -0
- package/agent/index.js +43 -18
- package/agent/lib/commands.js +794 -135
- package/agent/lib/redraw.js +124 -39
- package/agent/lib/sandbox.js +10 -1
- package/agent/lib/sdk.js +21 -0
- package/docs/MIGRATION.md +425 -0
- package/docs/PRESETS.md +210 -0
- package/docs/docs.json +91 -37
- package/docs/guide/best-practices-polling.mdx +154 -0
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/getting-started/configuration.mdx +380 -0
- package/docs/v7/getting-started/quickstart.mdx +273 -140
- package/docs/v7/guides/best-practices.mdx +486 -0
- package/docs/v7/guides/caching-ai.mdx +215 -0
- package/docs/v7/guides/caching-selectors.mdx +292 -0
- package/docs/v7/guides/caching.mdx +366 -0
- package/docs/v7/guides/ci-cd/azure.mdx +587 -0
- package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
- package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
- package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
- package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
- package/docs/v7/guides/ci-cd/travis.mdx +438 -0
- package/docs/v7/guides/debugging.mdx +349 -0
- package/docs/v7/guides/faq.mdx +393 -0
- package/docs/v7/guides/performance.mdx +517 -0
- package/docs/v7/guides/troubleshooting.mdx +526 -0
- package/docs/v7/guides/vitest-plugin.mdx +477 -0
- package/docs/v7/guides/vitest.mdx +535 -0
- package/docs/v7/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +287 -0
- package/docs/v7/presets/electron.mdx +435 -0
- package/docs/v7/presets/vscode.mdx +398 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/docs/v7/progressive-apis/CORE.md +459 -0
- package/docs/v7/progressive-apis/HOOKS.md +360 -0
- package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
- package/docs/v7/progressive-apis/PROVISION.md +266 -0
- package/interfaces/vitest-plugin.mjs +186 -100
- package/package.json +12 -1
- package/sdk.d.ts +335 -42
- package/sdk.js +756 -95
- package/src/core/Dashcam.js +469 -0
- package/src/core/index.d.ts +150 -0
- package/src/core/index.js +12 -0
- package/src/presets/index.mjs +331 -0
- package/src/vitest/extended.mjs +108 -0
- package/src/vitest/hooks.d.ts +119 -0
- package/src/vitest/hooks.mjs +298 -0
- package/src/vitest/index.mjs +64 -0
- package/src/vitest/lifecycle.mjs +277 -0
- package/src/vitest/utils.mjs +150 -0
- package/test/dashcam.test.js +137 -0
- package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
- package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
- package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
- package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
- package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
- package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
- package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
- package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
- package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
- package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
- package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
- package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
- package/testdriver/acceptance-sdk/type.test.mjs +19 -58
- package/vitest.config.mjs +1 -0
- package/.vscode/mcp.json +0 -9
- package/MIGRATION.md +0 -389
- package/PLUGIN_MIGRATION.md +0 -222
- package/PROMPT_CACHE.md +0 -200
- package/SDK_LOGGING.md +0 -222
- package/SDK_MIGRATION.md +0 -474
- package/SDK_README.md +0 -1122
- package/debug-screenshot-1763401388589.png +0 -0
- package/examples/run-tests-with-recording.sh +0 -70
- package/examples/screenshot-example.js +0 -63
- package/examples/sdk-awesome-logs-demo.js +0 -177
- package/examples/sdk-cache-thresholds.js +0 -96
- package/examples/sdk-element-properties.js +0 -155
- package/examples/sdk-simple-example.js +0 -65
- package/examples/test-recording-example.test.js +0 -166
- package/mcp-server/AI_GUIDELINES.md +0 -57
- package/test-find-api.js +0 -73
- package/test-prompt-cache.js +0 -96
- package/test-sandbox-render.js +0 -28
- package/test-sdk-methods.js +0 -15
- package/test-sdk-refactor.js +0 -53
- package/test-stack-trace.mjs +0 -57
- 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
|
|
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 =
|
|
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
|
-
|
|
1765
|
-
|
|
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(
|
|
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
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
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(
|
|
1791
|
-
fs.unlinkSync(
|
|
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
|
|
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.
|