testdriverai 7.3.4 → 7.3.5

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 (32) 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 +4 -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/interfaces/vitest-plugin.mjs +50 -18
  30. package/package.json +3 -1
  31. package/docs/v7/examples.mdx +0 -5
  32. package/jsconfig.json +0 -26
@@ -31,7 +31,7 @@ jobs:
31
31
 
32
32
  - name: Run Linux tests with Sentry Cron monitoring
33
33
  run: |
34
- sentry-cli monitors run testdriver-linux-acceptance -- vitest run examples/*.test.mjs
34
+ sentry-cli monitors run testdriver-linux-acceptance -- npx vitest run examples/*.test.mjs
35
35
  env:
36
36
  SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
37
37
  TD_API_KEY: ${{ secrets.TD_API_KEY }}
@@ -18,6 +18,8 @@ jobs:
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v4
21
+ with:
22
+ ref: ${{ github.head_ref }}
21
23
 
22
24
  - name: Setup Node.js
23
25
  uses: actions/setup-node@v4
@@ -86,11 +88,46 @@ jobs:
86
88
  if: always() && contains(github.event.pull_request.labels.*.name, 'test-windows')
87
89
 
88
90
  steps:
91
+ - uses: actions/checkout@v4
92
+ with:
93
+ ref: ${{ github.head_ref }}
94
+
95
+ - name: Setup Node.js
96
+ uses: actions/setup-node@v4
97
+ with:
98
+ node-version: "20"
99
+ cache: "npm"
100
+
101
+ - name: Install dependencies
102
+ run: npm ci
103
+
89
104
  - name: Download test results
90
105
  uses: actions/download-artifact@v4
91
106
  with:
92
107
  name: test-results-windows
93
108
 
109
+ - name: Download test output
110
+ uses: actions/download-artifact@v4
111
+ with:
112
+ name: test-output-windows
113
+
114
+ - name: Extract example URLs from Windows tests
115
+ if: needs.test-windows.result == 'success'
116
+ run: node docs/_scripts/extract-example-urls.js --file=test-output.log
117
+
118
+ - name: Generate example docs
119
+ if: needs.test-windows.result == 'success'
120
+ run: node docs/_scripts/generate-examples.js --skip-ai
121
+
122
+ - name: Commit updated docs
123
+ if: needs.test-windows.result == 'success'
124
+ run: |
125
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
126
+ git config --local user.name "github-actions[bot]"
127
+ git add docs/
128
+ git diff --staged --quiet || git commit -m "docs: update example documentation from Windows tests [skip ci]"
129
+ git push || echo "No changes to push"
130
+
94
131
  - name: Upload test results to Sentry Prevent
95
132
  if: ${{ !cancelled() }}
96
133
  uses: getsentry/prevent-action@v0
@@ -103,4 +140,4 @@ jobs:
103
140
  with:
104
141
  files: test-report.junit.xml
105
142
  comment_mode: always
106
- check_name: Test Results (Windows)
143
+ check_name: Test Results (Windows)
@@ -51,7 +51,7 @@ jobs:
51
51
  TWOCAPTCHA_API_KEY: ${{ secrets.TWOCAPTCHA_API_KEY }}
52
52
 
53
53
  - name: Run Windows tests with self-hosted instances
54
- run: vitest run ${{ inputs.test_pattern }}
54
+ run: npx vitest run ${{ inputs.test_pattern }} 2>&1 | tee test-output.log
55
55
  env:
56
56
  TD_API_KEY: ${{ secrets.TD_API_KEY }}
57
57
  TWOCAPTCHA_API_KEY: ${{ secrets.TWOCAPTCHA_API_KEY }}
@@ -72,6 +72,14 @@ jobs:
72
72
  path: test-report.junit.xml
73
73
  retention-days: 30
74
74
 
75
+ - name: Upload test output log
76
+ if: always()
77
+ uses: actions/upload-artifact@v4
78
+ with:
79
+ name: test-output-windows
80
+ path: test-output.log
81
+ retention-days: 30
82
+
75
83
  - name: Upload TestDriver AI CLI logs
76
84
  if: always()
77
85
  uses: actions/upload-artifact@v4
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [7.3.5](https://github.com/testdriverai/testdriverai/compare/v7.3.4...v7.3.5) (2026-02-07)
2
+
3
+
4
+
1
5
  ## [7.3.4](https://github.com/testdriverai/testdriverai/compare/v7.3.2...v7.3.4) (2026-02-06)
2
6
 
3
7
 
@@ -0,0 +1,105 @@
1
+ {
2
+ "$schema": "./examples-manifest.schema.json",
3
+ "examples": {
4
+ "assert.test.mjs": {
5
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852cedeae78746d7ac0c25",
6
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
7
+ },
8
+ "drag-and-drop.test.mjs": {
9
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/6985279beae78746d7ac0ba4",
10
+ "lastUpdated": "2026-02-06T00:04:26.811Z"
11
+ },
12
+ "exec-pwsh.test.mjs": {
13
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/6985279ceae78746d7ac0ba6",
14
+ "lastUpdated": "2026-02-06T00:04:26.811Z"
15
+ },
16
+ "match-image.test.mjs": {
17
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/6985279eeae78746d7ac0ba7",
18
+ "lastUpdated": "2026-02-06T00:04:26.811Z"
19
+ },
20
+ "scroll-until-text.test.mjs": {
21
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/698527ae57e74ea13445e9ca",
22
+ "lastUpdated": "2026-02-06T00:04:26.811Z"
23
+ },
24
+ "hover-text-with-description.test.mjs": {
25
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/698528d157e74ea13445e9fc",
26
+ "lastUpdated": "2026-02-06T00:04:26.812Z"
27
+ },
28
+ "windows-installer.test.mjs": {
29
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852931eae78746d7ac0be6",
30
+ "lastUpdated": "2026-02-06T00:04:26.812Z"
31
+ },
32
+ "exec-output.test.mjs": {
33
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/698528d257e74ea13445e9fd",
34
+ "lastUpdated": "2026-02-06T00:04:26.812Z"
35
+ },
36
+ "chrome-extension.test.mjs": {
37
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852a34eae78746d7ac0bf0",
38
+ "lastUpdated": "2026-02-06T00:04:27.030Z"
39
+ },
40
+ "launch-vscode-linux.test.mjs": {
41
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/698527b057e74ea13445e9ce",
42
+ "lastUpdated": "2026-02-06T00:04:26.812Z"
43
+ },
44
+ "hover-image.test.mjs": {
45
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852a31b8ceaf4540e27312",
46
+ "lastUpdated": "2026-02-06T00:04:27.029Z"
47
+ },
48
+ "installer.test.mjs": {
49
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852932eae78746d7ac0be8",
50
+ "lastUpdated": "2026-02-06T00:04:26.812Z"
51
+ },
52
+ "type.test.mjs": {
53
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852d10eae78746d7ac0c2e",
54
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
55
+ },
56
+ "press-keys.test.mjs": {
57
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852a8ab8ceaf4540e2732c",
58
+ "lastUpdated": "2026-02-06T00:04:27.030Z"
59
+ },
60
+ "scroll-keyboard.test.mjs": {
61
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852befeae78746d7ac0c11",
62
+ "lastUpdated": "2026-02-06T00:04:27.030Z"
63
+ },
64
+ "scroll.test.mjs": {
65
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852ba9b8ceaf4540e2733d",
66
+ "lastUpdated": "2026-02-06T00:04:27.030Z"
67
+ },
68
+ "scroll-until-image.test.mjs": {
69
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852cefeae78746d7ac0c27",
70
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
71
+ },
72
+ "prompt.test.mjs": {
73
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852cf0eae78746d7ac0c28",
74
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
75
+ },
76
+ "focus-window.test.mjs": {
77
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852cf1eae78746d7ac0c2a",
78
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
79
+ },
80
+ "captcha-api.test.mjs": {
81
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852e9db3d27441a2d96ed7",
82
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
83
+ },
84
+ "element-not-found.test.mjs": {
85
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852e57eae78746d7ac0c3f",
86
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
87
+ },
88
+ "formatted-logging.test.mjs": {
89
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852e1ceae78746d7ac0c39",
90
+ "lastUpdated": "2026-02-06T00:04:27.031Z"
91
+ },
92
+ "hover-text.test.mjs": {
93
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852f8beae78746d7ac0c5e",
94
+ "lastUpdated": "2026-02-06T00:04:27.032Z"
95
+ },
96
+ "no-provision.test.mjs": {
97
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852fd7eae78746d7ac0c66",
98
+ "lastUpdated": "2026-02-06T00:04:27.032Z"
99
+ },
100
+ "ai.test.mjs": {
101
+ "url": "https://console.testdriver.ai/runs/6985263ceae78746d7ac0abf/69852f70eae78746d7ac0c56",
102
+ "lastUpdated": "2026-02-06T00:04:27.032Z"
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Examples Manifest",
4
+ "description": "Maps example test files to their test run URLs for documentation embedding",
5
+ "type": "object",
6
+ "properties": {
7
+ "$schema": {
8
+ "type": "string"
9
+ },
10
+ "examples": {
11
+ "type": "object",
12
+ "additionalProperties": {
13
+ "type": "object",
14
+ "properties": {
15
+ "url": {
16
+ "type": "string",
17
+ "description": "Full URL to the test run (without ?embed=true)",
18
+ "pattern": "^https://console\\.testdriver\\.ai/runs/.+"
19
+ },
20
+ "lastUpdated": {
21
+ "type": "string",
22
+ "format": "date-time",
23
+ "description": "ISO timestamp of when this URL was last updated"
24
+ },
25
+ "title": {
26
+ "type": "string",
27
+ "description": "Human-readable title extracted from describe() block"
28
+ },
29
+ "testName": {
30
+ "type": "string",
31
+ "description": "Test name extracted from it() block"
32
+ }
33
+ },
34
+ "required": ["url", "lastUpdated"],
35
+ "additionalProperties": false
36
+ }
37
+ }
38
+ },
39
+ "required": ["examples"],
40
+ "additionalProperties": false
41
+ }
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Extract Example URLs from CI Logs
5
+ *
6
+ * Parses vitest output to extract TESTDRIVER_EXAMPLE_URL lines
7
+ * and updates the examples-manifest.json file.
8
+ *
9
+ * Usage:
10
+ * cat ci-log.txt | node extract-example-urls.js
11
+ * node extract-example-urls.js < ci-log.txt
12
+ * node extract-example-urls.js --file=ci-log.txt
13
+ */
14
+
15
+ const fs = require("fs");
16
+ const path = require("path");
17
+ const readline = require("readline");
18
+
19
+ const MANIFEST_PATH = path.join(__dirname, "../_data/examples-manifest.json");
20
+
21
+ // Regex to match TESTDRIVER_EXAMPLE_URL::filename::url (handles optional timestamp prefix from CI logs)
22
+ const URL_PATTERN = /TESTDRIVER_EXAMPLE_URL::([^:]+)::(.+)$/;
23
+
24
+ // Parse command line arguments
25
+ function parseArgs() {
26
+ const args = process.argv.slice(2);
27
+ const options = {
28
+ file: null,
29
+ help: false,
30
+ };
31
+
32
+ for (const arg of args) {
33
+ if (arg === "--help" || arg === "-h") {
34
+ options.help = true;
35
+ } else if (arg.startsWith("--file=")) {
36
+ options.file = arg.slice(7);
37
+ }
38
+ }
39
+
40
+ return options;
41
+ }
42
+
43
+ // Load existing manifest or create new one
44
+ function loadManifest() {
45
+ try {
46
+ const content = fs.readFileSync(MANIFEST_PATH, "utf-8");
47
+ return JSON.parse(content);
48
+ } catch (error) {
49
+ return {
50
+ "$schema": "./examples-manifest.schema.json",
51
+ "examples": {},
52
+ };
53
+ }
54
+ }
55
+
56
+ // Save manifest
57
+ function saveManifest(manifest) {
58
+ const dir = path.dirname(MANIFEST_PATH);
59
+ if (!fs.existsSync(dir)) {
60
+ fs.mkdirSync(dir, { recursive: true });
61
+ }
62
+ fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
63
+ }
64
+
65
+ // Process a single line and extract URL if present
66
+ function processLine(line, manifest, stats) {
67
+ const match = line.match(URL_PATTERN);
68
+ if (match) {
69
+ const [, filename, url] = match;
70
+ const isNew = !manifest.examples[filename];
71
+
72
+ manifest.examples[filename] = {
73
+ url: url.trim(),
74
+ lastUpdated: new Date().toISOString(),
75
+ };
76
+
77
+ if (isNew) {
78
+ stats.added++;
79
+ } else {
80
+ stats.updated++;
81
+ }
82
+
83
+ console.log(`${isNew ? "āž•" : "šŸ”„"} ${filename}: ${url}`);
84
+ }
85
+ }
86
+
87
+ // Process input stream
88
+ async function processInput(inputStream) {
89
+ const manifest = loadManifest();
90
+ const stats = { added: 0, updated: 0 };
91
+
92
+ const rl = readline.createInterface({
93
+ input: inputStream,
94
+ crlfDelay: Infinity,
95
+ });
96
+
97
+ for await (const line of rl) {
98
+ processLine(line, manifest, stats);
99
+ }
100
+
101
+ if (stats.added > 0 || stats.updated > 0) {
102
+ saveManifest(manifest);
103
+ console.log(`\n✨ Manifest updated: ${stats.added} added, ${stats.updated} updated`);
104
+ console.log(`šŸ“‚ Written to: ${MANIFEST_PATH}`);
105
+ } else {
106
+ console.log("\nāš ļø No TESTDRIVER_EXAMPLE_URL entries found in input");
107
+ }
108
+
109
+ return stats;
110
+ }
111
+
112
+ // Show help
113
+ function showHelp() {
114
+ console.log(`
115
+ Extract Example URLs from CI Logs
116
+
117
+ Usage:
118
+ cat ci-log.txt | node extract-example-urls.js
119
+ node extract-example-urls.js < ci-log.txt
120
+ node extract-example-urls.js --file=ci-log.txt
121
+
122
+ Options:
123
+ --file=<path> Read from file instead of stdin
124
+ --help, -h Show this help message
125
+
126
+ Description:
127
+ Parses CI log output looking for lines matching:
128
+ TESTDRIVER_EXAMPLE_URL::<filename>::<url>
129
+
130
+ Updates docs/_data/examples-manifest.json with the extracted URLs.
131
+ Existing entries are updated, new entries are added.
132
+ `);
133
+ }
134
+
135
+ // Main function
136
+ async function main() {
137
+ const options = parseArgs();
138
+
139
+ if (options.help) {
140
+ showHelp();
141
+ process.exit(0);
142
+ }
143
+
144
+ console.log("šŸ” Extracting example URLs from input...\n");
145
+
146
+ let inputStream;
147
+ if (options.file) {
148
+ if (!fs.existsSync(options.file)) {
149
+ console.error(`āŒ File not found: ${options.file}`);
150
+ process.exit(1);
151
+ }
152
+ inputStream = fs.createReadStream(options.file);
153
+ } else {
154
+ inputStream = process.stdin;
155
+ }
156
+
157
+ try {
158
+ await processInput(inputStream);
159
+ } catch (error) {
160
+ console.error(`āŒ Error: ${error.message}`);
161
+ process.exit(1);
162
+ }
163
+ }
164
+
165
+ main();