testdriverai 7.3.4 → 7.3.6

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 (60) hide show
  1. package/.github/workflows/acceptance-linux-scheduled.yaml +1 -1
  2. package/.github/workflows/acceptance.yaml +38 -1
  3. package/.github/workflows/windows-self-hosted.yaml +9 -1
  4. package/CHANGELOG.md +8 -0
  5. package/docs/_data/examples-manifest.json +105 -0
  6. package/docs/_data/examples-manifest.schema.json +41 -0
  7. package/docs/_scripts/extract-example-urls.js +165 -0
  8. package/docs/_scripts/generate-examples.js +534 -0
  9. package/docs/docs.json +242 -212
  10. package/docs/v7/aws-setup.mdx +1 -1
  11. package/docs/v7/examples/ai.mdx +72 -0
  12. package/docs/v7/examples/assert.mdx +72 -0
  13. package/docs/v7/examples/captcha-api.mdx +92 -0
  14. package/docs/v7/examples/chrome-extension.mdx +132 -0
  15. package/docs/v7/examples/drag-and-drop.mdx +100 -0
  16. package/docs/v7/examples/element-not-found.mdx +67 -0
  17. package/docs/v7/examples/hover-image.mdx +94 -0
  18. package/docs/v7/examples/hover-text.mdx +69 -0
  19. package/docs/v7/examples/installer.mdx +91 -0
  20. package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
  21. package/docs/v7/examples/match-image.mdx +96 -0
  22. package/docs/v7/examples/press-keys.mdx +92 -0
  23. package/docs/v7/examples/scroll-keyboard.mdx +79 -0
  24. package/docs/v7/examples/scroll-until-image.mdx +81 -0
  25. package/docs/v7/examples/scroll-until-text.mdx +109 -0
  26. package/docs/v7/examples/scroll.mdx +81 -0
  27. package/docs/v7/examples/type.mdx +92 -0
  28. package/docs/v7/examples/windows-installer.mdx +89 -0
  29. package/examples/ai.test.mjs +2 -1
  30. package/examples/assert.test.mjs +2 -2
  31. package/examples/captcha-api.test.mjs +3 -2
  32. package/examples/chrome-extension.test.mjs +3 -2
  33. package/examples/config.mjs +5 -0
  34. package/examples/drag-and-drop.test.mjs +2 -1
  35. package/examples/element-not-found.test.mjs +2 -1
  36. package/examples/exec-output.test.mjs +2 -1
  37. package/examples/exec-pwsh.test.mjs +2 -1
  38. package/examples/focus-window.test.mjs +2 -1
  39. package/examples/formatted-logging.test.mjs +2 -1
  40. package/examples/hover-image.test.mjs +2 -1
  41. package/examples/hover-text-with-description.test.mjs +2 -1
  42. package/examples/hover-text.test.mjs +2 -1
  43. package/examples/installer.test.mjs +3 -2
  44. package/examples/launch-vscode-linux.test.mjs +3 -2
  45. package/examples/match-image.test.mjs +2 -1
  46. package/examples/no-provision.test.mjs +2 -3
  47. package/examples/press-keys.test.mjs +7 -13
  48. package/examples/prompt.test.mjs +2 -1
  49. package/examples/scroll-keyboard.test.mjs +2 -1
  50. package/examples/scroll-until-image.test.mjs +2 -1
  51. package/examples/scroll-until-text.test.mjs +2 -1
  52. package/examples/scroll.test.mjs +2 -1
  53. package/examples/type.test.mjs +3 -2
  54. package/examples/windows-installer.test.mjs +2 -1
  55. package/interfaces/vitest-plugin.mjs +50 -18
  56. package/package.json +3 -1
  57. package/sdk.js +49 -38
  58. package/vitest.config.mjs +1 -1
  59. package/docs/v7/examples.mdx +0 -5
  60. package/jsconfig.json +0 -26
@@ -14,30 +14,54 @@ const require = createRequire(import.meta.url);
14
14
  */
15
15
  const MINIMUM_VITEST_VERSION = 4;
16
16
 
17
+ /**
18
+ * Try to read vitest's package.json version using multiple resolution strategies.
19
+ * Vitest's Vite-based transform pipeline can rewrite import.meta.url, causing
20
+ * createRequire to resolve from the wrong location. We fall back to resolving
21
+ * from process.cwd() and then to reading directly from node_modules.
22
+ * @returns {string|null} The vitest version string, or null if not found
23
+ */
24
+ function resolveVitestVersion() {
25
+ // Strategy 1: createRequire from import.meta.url (standard CJS interop)
26
+ try {
27
+ return require("vitest/package.json").version;
28
+ } catch {}
29
+
30
+ // Strategy 2: createRequire from process.cwd() (works when import.meta.url is rewritten)
31
+ try {
32
+ const cwdRequire = createRequire(path.join(process.cwd(), "package.json"));
33
+ return cwdRequire("vitest/package.json").version;
34
+ } catch {}
35
+
36
+ // Strategy 3: read directly from node_modules on disk
37
+ try {
38
+ const vitestPkgPath = path.join(process.cwd(), "node_modules", "vitest", "package.json");
39
+ return JSON.parse(fs.readFileSync(vitestPkgPath, "utf8")).version;
40
+ } catch {}
41
+
42
+ return null;
43
+ }
44
+
17
45
  /**
18
46
  * Check that Vitest version meets minimum requirements
19
47
  * @throws {Error} if Vitest version is below minimum or not installed
20
48
  */
21
49
  function checkVitestVersion() {
22
- try {
23
- const vitestPkg = require("vitest/package.json");
24
- const version = vitestPkg.version;
25
- const major = parseInt(version.split(".")[0], 10);
50
+ const version = resolveVitestVersion();
26
51
 
27
- if (major < MINIMUM_VITEST_VERSION) {
28
- throw new Error(
29
- `TestDriver requires Vitest >= ${MINIMUM_VITEST_VERSION}.0.0, but found ${version}. ` +
30
- `Please upgrade Vitest: npm install vitest@latest`,
31
- );
32
- }
33
- } catch (err) {
34
- if (err.code === "MODULE_NOT_FOUND") {
35
- throw new Error(
36
- "TestDriver requires Vitest to be installed. " +
37
- "Please install it: npm install vitest@latest",
38
- );
39
- }
40
- throw err;
52
+ if (!version) {
53
+ throw new Error(
54
+ "TestDriver requires Vitest to be installed. " +
55
+ "Please install it: npm install vitest@latest",
56
+ );
57
+ }
58
+
59
+ const major = parseInt(version.split(".")[0], 10);
60
+ if (major < MINIMUM_VITEST_VERSION) {
61
+ throw new Error(
62
+ `TestDriver requires Vitest >= ${MINIMUM_VITEST_VERSION}.0.0, but found ${version}. ` +
63
+ `Please upgrade Vitest: npm install vitest@latest`,
64
+ );
41
65
  }
42
66
  }
43
67
 
@@ -1013,6 +1037,14 @@ class TestDriverReporter {
1013
1037
  console.log(
1014
1038
  `🔗 Test Report: ${getConsoleUrl(pluginState.apiRoot)}/runs/${testRunDbId}/${testCaseDbId}`,
1015
1039
  );
1040
+
1041
+ // Output parseable format for docs generation (examples only)
1042
+ if (testFile.startsWith("examples/")) {
1043
+ const testFileName = path.basename(testFile);
1044
+ console.log(
1045
+ `TESTDRIVER_EXAMPLE_URL::${testFileName}::${getConsoleUrl(pluginState.apiRoot)}/runs/${testRunDbId}/${testCaseDbId}`,
1046
+ );
1047
+ }
1016
1048
  } catch (error) {
1017
1049
  logger.error("Failed to report test case:", error.message);
1018
1050
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "7.3.4",
3
+ "version": "7.3.6",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "sdk.js",
6
6
  "types": "sdk.d.ts",
@@ -42,6 +42,8 @@
42
42
  "docs:build": "npm run docs:skills && cd docs && npx mint@latest build",
43
43
  "docs:links": "node docs/_scripts/link-replacer.js",
44
44
  "docs:skills": "node docs/_scripts/generate-skills.js",
45
+ "docs:examples": "node docs/_scripts/generate-examples.js",
46
+ "docs:extract-urls": "node docs/_scripts/extract-example-urls.js",
45
47
  "bundle": "node build.mjs",
46
48
  "test": "mocha test/*",
47
49
  "test:sdk": "vitest run",
package/sdk.js CHANGED
@@ -1567,6 +1567,51 @@ class TestDriverSDK {
1567
1567
  return "C:\\PROGRA~1\\nodejs\\node_modules\\dashcam-chrome\\build";
1568
1568
  }
1569
1569
 
1570
+ /**
1571
+ * Wait for Chrome DevTools Protocol debugger to be ready on port 9222,
1572
+ * then wait for a page to report loaded.
1573
+ * Works on both Windows (PowerShell) and Linux (sh).
1574
+ * @param {number} [timeoutMs=60000] - Maximum time to wait in ms
1575
+ * @returns {Promise<void>}
1576
+ */
1577
+ async _waitForChromeDebuggerReady(timeoutMs = 60000) {
1578
+ const shell = this.os === "windows" ? "pwsh" : "sh";
1579
+
1580
+ if (this.os === "windows") {
1581
+ // Wait for port 9222 to be listening
1582
+ await this.exec(
1583
+ shell,
1584
+ `$timeout = ${Math.floor(timeoutMs / 1000)}; $elapsed = 0; while ($elapsed -lt $timeout) { try { $tcp = New-Object System.Net.Sockets.TcpClient; $tcp.Connect('127.0.0.1', 9222); $tcp.Close(); break } catch { Start-Sleep -Milliseconds 200; $elapsed += 0.2 } }`,
1585
+ timeoutMs,
1586
+ true,
1587
+ );
1588
+
1589
+ // Wait for a page target to appear via CDP
1590
+ await this.exec(
1591
+ shell,
1592
+ `$timeout = ${Math.floor(timeoutMs / 1000)}; $elapsed = 0; while ($elapsed -lt $timeout) { try { $r = Invoke-RestMethod -Uri 'http://localhost:9222/json' -TimeoutSec 2; if ($r | Where-Object { $_.type -eq 'page' }) { break } } catch {} Start-Sleep -Milliseconds 500; $elapsed += 0.5 }`,
1593
+ timeoutMs,
1594
+ true,
1595
+ );
1596
+ } else {
1597
+ // Wait for port 9222 to be listening
1598
+ await this.exec(
1599
+ shell,
1600
+ `timeout=${Math.floor(timeoutMs / 1000)}; elapsed=0; while [ $elapsed -lt $timeout ]; do nc -z localhost 9222 && break; sleep 0.2; elapsed=$((elapsed + 1)); done`,
1601
+ timeoutMs,
1602
+ true,
1603
+ );
1604
+
1605
+ // Wait for a page target to appear via CDP
1606
+ await this.exec(
1607
+ shell,
1608
+ `timeout=${Math.floor(timeoutMs / 1000)}; elapsed=0; while [ $elapsed -lt $timeout ]; do curl -s http://localhost:9222/json 2>/dev/null | grep -q '"type": "page"' && break; sleep 0.5; elapsed=$((elapsed + 1)); done`,
1609
+ timeoutMs,
1610
+ true,
1611
+ );
1612
+ }
1613
+ }
1614
+
1570
1615
  _createProvisionAPI() {
1571
1616
  const self = this;
1572
1617
 
@@ -1691,31 +1736,9 @@ class TestDriverSDK {
1691
1736
  );
1692
1737
  }
1693
1738
 
1694
- // Wait for Chrome to be ready
1739
+ // Wait for Chrome debugger port and page to be ready
1740
+ await this._waitForChromeDebuggerReady();
1695
1741
  await this.focusApplication("Google Chrome");
1696
-
1697
- // Wait for URL to load
1698
- try {
1699
- const urlObj = new URL(url);
1700
- const domain = urlObj.hostname;
1701
-
1702
- for (let attempt = 0; attempt < 30; attempt++) {
1703
- const result = await this.find(`${domain}`);
1704
-
1705
- if (result.found()) {
1706
- break;
1707
- } else {
1708
- await new Promise((resolve) => setTimeout(resolve, 1000));
1709
- }
1710
- }
1711
-
1712
- await this.focusApplication("Google Chrome");
1713
- } catch (e) {
1714
- console.warn(
1715
- `[provision.chrome] ⚠️ Could not parse URL "${url}":`,
1716
- e.message,
1717
- );
1718
- }
1719
1742
  },
1720
1743
 
1721
1744
  /**
@@ -1977,20 +2000,8 @@ with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
1977
2000
  );
1978
2001
  }
1979
2002
 
1980
- // Wait for Chrome to be ready
1981
- await this.focusApplication("Google Chrome");
1982
-
1983
- // Wait for New Tab to appear
1984
- for (let attempt = 0; attempt < 30; attempt++) {
1985
- const result = await this.find("New Tab");
1986
-
1987
- if (result.found()) {
1988
- break;
1989
- } else {
1990
- await new Promise((resolve) => setTimeout(resolve, 1000));
1991
- }
1992
- }
1993
-
2003
+ // Wait for Chrome debugger port and page to be ready
2004
+ await this._waitForChromeDebuggerReady();
1994
2005
  await this.focusApplication("Google Chrome");
1995
2006
  },
1996
2007
 
package/vitest.config.mjs CHANGED
@@ -13,7 +13,7 @@ export default defineConfig({
13
13
  testTimeout: 900000,
14
14
  hookTimeout: 900000,
15
15
  disableConsoleIntercept: true,
16
- maxConcurrency: 3,
16
+ maxConcurrency: 100,
17
17
  reporters: [
18
18
  "default",
19
19
  TestDriver(),
@@ -1,5 +0,0 @@
1
- ---
2
- title: "Examples"
3
- url: "https://github.com/testdriverai/testdriverai/tree/main/examples"
4
- icon: 'code'
5
- ---
package/jsconfig.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "ESNext",
4
- "moduleResolution": "bundler",
5
- "target": "ES2022",
6
- "checkJs": true,
7
- "strict": false,
8
- "allowSyntheticDefaultImports": true,
9
- "esModuleInterop": true,
10
- "baseUrl": ".",
11
- "typeRoots": ["."]
12
- },
13
- "include": [
14
- "**/*.js",
15
- "**/*.mjs",
16
- "**/*.d.ts",
17
- "sdk.d.ts",
18
- "lib/**/*.d.ts",
19
- "interfaces/**/*.d.ts"
20
- ],
21
- "exclude": [
22
- "node_modules",
23
- "dist",
24
- "build"
25
- ]
26
- }