testdriverai 7.9.81-test → 7.9.91-canary
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/agent/lib/provision-commands.js +38 -11
- package/docs/_data/examples-manifest.json +52 -52
- package/docs/v7/examples/ai.mdx +1 -1
- package/docs/v7/examples/assert.mdx +1 -1
- package/docs/v7/examples/chrome-extension.mdx +30 -13
- package/docs/v7/examples/element-not-found.mdx +1 -1
- package/docs/v7/examples/findall-coffee-icons.mdx +1 -1
- package/docs/v7/examples/hover-image.mdx +1 -1
- package/docs/v7/examples/hover-text-with-description.mdx +1 -1
- package/docs/v7/examples/hover-text.mdx +1 -1
- package/docs/v7/examples/installer.mdx +1 -1
- package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
- package/docs/v7/examples/parse.mdx +1 -1
- package/docs/v7/examples/press-keys.mdx +1 -1
- package/docs/v7/examples/scroll-keyboard.mdx +1 -1
- package/docs/v7/examples/scroll.mdx +1 -1
- package/docs/v7/examples/type.mdx +1 -1
- package/examples/chrome-extension.test.mjs +29 -12
- package/lib/core/Dashcam.js +18 -0
- package/lib/provision.js +749 -0
- package/package.json +1 -1
- package/sdk.js +2 -727
|
@@ -13,6 +13,24 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Extract the major.minor portion of a semver-ish version string.
|
|
18
|
+
*
|
|
19
|
+
* Examples:
|
|
20
|
+
* '7.9.59' -> '7.9'
|
|
21
|
+
* '7.9.59-test' -> '7.9'
|
|
22
|
+
* '7.10.0-canary.3'-> '7.10'
|
|
23
|
+
* '' -> ''
|
|
24
|
+
*
|
|
25
|
+
* @param {string} version
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
function majorMinor(version) {
|
|
29
|
+
if (!version || typeof version !== 'string') return '';
|
|
30
|
+
var m = version.match(/^(\d+)\.(\d+)/);
|
|
31
|
+
return m ? m[1] + '.' + m[2] : '';
|
|
32
|
+
}
|
|
33
|
+
|
|
16
34
|
/**
|
|
17
35
|
* Build the agent config object written to the sandbox.
|
|
18
36
|
*
|
|
@@ -98,23 +116,27 @@ function windowsProvisionCommands({ channel, configJson, sandboxId, s3DownloadUr
|
|
|
98
116
|
|
|
99
117
|
// If we know the image version, check whether the baked-in runner already
|
|
100
118
|
// matches — skip npm install entirely when it does (saves 5-15s per launch).
|
|
119
|
+
// Only the major.minor portion is compared (patch & prerelease suffix are
|
|
120
|
+
// ignored) so trivial patch bumps don't trigger an unnecessary npm install.
|
|
101
121
|
// Emits a structured RUNNER_VERSION_CHECK line so SSM output / runner logs
|
|
102
122
|
// capture the outcome for monitoring.
|
|
103
123
|
if (imageVersion) {
|
|
124
|
+
var expectedMinor = majorMinor(imageVersion);
|
|
104
125
|
commands.push(
|
|
105
126
|
"Write-Host 'Checking installed runner version...'",
|
|
106
127
|
"$installedVersion = ''",
|
|
107
128
|
"try { $pkg = Get-Content 'node_modules/@testdriverai/runner/package.json' -Raw | ConvertFrom-Json; $installedVersion = $pkg.version } catch {}",
|
|
108
|
-
"if ($installedVersion -
|
|
109
|
-
"
|
|
110
|
-
" Write-Host
|
|
129
|
+
"$installedMinor = if ($installedVersion) { ($installedVersion -split '[.-]')[0..1] -join '.' } else { '' }",
|
|
130
|
+
"if (('" + expectedMinor + "' -ne '') -and ($installedMinor -eq '" + expectedMinor + "')) {",
|
|
131
|
+
" Write-Host \"Runner already at v$installedVersion (minor " + expectedMinor + "), skipping update\"",
|
|
132
|
+
" Write-Host (\"RUNNER_VERSION_CHECK:\" + (ConvertTo-Json -Compress @{ action='skipped'; installedVersion=$installedVersion; expectedVersion='" + imageVersion + "'; expectedMinor='" + expectedMinor + "'; channel='" + channel + "'; sandboxId='" + sandboxId + "' }))",
|
|
111
133
|
"} else {",
|
|
112
|
-
" Write-Host \"Installed: $
|
|
134
|
+
" Write-Host \"Installed minor: $installedMinor, expected: " + expectedMinor + " — updating...\"",
|
|
113
135
|
" Write-Host 'Installing @testdriverai/runner@" + runnerTag + "...'",
|
|
114
136
|
' npm install @testdriverai/runner@' + runnerTag + ' --omit=dev 2>&1 | Write-Host',
|
|
115
137
|
" $newVersion = ''",
|
|
116
138
|
" try { $newPkg = Get-Content 'node_modules/@testdriverai/runner/package.json' -Raw | ConvertFrom-Json; $newVersion = $newPkg.version } catch {}",
|
|
117
|
-
" Write-Host (\"RUNNER_VERSION_CHECK:\" + (ConvertTo-Json -Compress @{ action='updated'; previousVersion=$installedVersion; expectedVersion='" + imageVersion + "'; newVersion=$newVersion; channel='" + channel + "'; sandboxId='" + sandboxId + "' }))",
|
|
139
|
+
" Write-Host (\"RUNNER_VERSION_CHECK:\" + (ConvertTo-Json -Compress @{ action='updated'; previousVersion=$installedVersion; expectedVersion='" + imageVersion + "'; expectedMinor='" + expectedMinor + "'; newVersion=$newVersion; channel='" + channel + "'; sandboxId='" + sandboxId + "' }))",
|
|
118
140
|
" Write-Host 'Runner install complete'",
|
|
119
141
|
"}"
|
|
120
142
|
);
|
|
@@ -197,20 +219,24 @@ function linuxRunnerInstallCommand({ channel, s3DownloadUrl, runnerPath, imageVe
|
|
|
197
219
|
].join(' && ');
|
|
198
220
|
}
|
|
199
221
|
|
|
200
|
-
// If we know the image version, wrap the install in a version check
|
|
222
|
+
// If we know the image version, wrap the install in a version check.
|
|
223
|
+
// Only the major.minor portion is compared (patch & prerelease suffix are
|
|
224
|
+
// ignored) so trivial patch bumps don't trigger an unnecessary npm install.
|
|
201
225
|
if (imageVersion) {
|
|
226
|
+
var expectedMinor = majorMinor(imageVersion);
|
|
202
227
|
return [
|
|
203
228
|
'INSTALLED_VERSION=$(node -p "try{require(\'' + rp + '/package.json\').version}catch(e){\'\'}" 2>/dev/null || echo "")',
|
|
204
|
-
'
|
|
205
|
-
'
|
|
206
|
-
' echo "
|
|
229
|
+
'INSTALLED_MINOR=$(echo "$INSTALLED_VERSION" | sed -E "s/^([0-9]+\\.[0-9]+).*/\\1/")',
|
|
230
|
+
'if [ -n "' + expectedMinor + '" ] && [ "$INSTALLED_MINOR" = "' + expectedMinor + '" ]; then',
|
|
231
|
+
' echo "RUNNER_VERSION_CHECK:{\\"action\\":\\"skipped\\",\\"installedVersion\\":\\"$INSTALLED_VERSION\\",\\"expectedVersion\\":\\"' + imageVersion + '\\",\\"expectedMinor\\":\\"' + expectedMinor + '\\",\\"channel\\":\\"' + channel + '\\",\\"sandboxId\\":\\"' + sid + '\\"}"',
|
|
232
|
+
' echo "Runner already at v$INSTALLED_VERSION (minor ' + expectedMinor + '), skipping update"',
|
|
207
233
|
'else',
|
|
208
|
-
' echo "Installed: $
|
|
234
|
+
' echo "Installed minor: $INSTALLED_MINOR, expected: ' + expectedMinor + ' — updating..."',
|
|
209
235
|
' sudo npm install -g @testdriverai/runner@' + runnerTag + ' --omit=dev --no-audit --no-fund --loglevel=error',
|
|
210
236
|
' sudo rm -rf ' + rp,
|
|
211
237
|
' sudo ln -sf $(npm root -g)/@testdriverai/runner ' + rp,
|
|
212
238
|
' NEW_VERSION=$(node -p "try{require(\'' + rp + '/package.json\').version}catch(e){\'\'}" 2>/dev/null || echo "")',
|
|
213
|
-
' echo "RUNNER_VERSION_CHECK:{\\"action\\":\\"updated\\",\\"previousVersion\\":\\"$INSTALLED_VERSION\\",\\"expectedVersion\\":\\"' + imageVersion + '\\",\\"newVersion\\":\\"$NEW_VERSION\\",\\"channel\\":\\"' + channel + '\\",\\"sandboxId\\":\\"' + sid + '\\"}"',
|
|
239
|
+
' echo "RUNNER_VERSION_CHECK:{\\"action\\":\\"updated\\",\\"previousVersion\\":\\"$INSTALLED_VERSION\\",\\"expectedVersion\\":\\"' + imageVersion + '\\",\\"expectedMinor\\":\\"' + expectedMinor + '\\",\\"newVersion\\":\\"$NEW_VERSION\\",\\"channel\\":\\"' + channel + '\\",\\"sandboxId\\":\\"' + sid + '\\"}"',
|
|
214
240
|
' echo "Runner install complete"',
|
|
215
241
|
'fi',
|
|
216
242
|
].join(' && ');
|
|
@@ -227,4 +253,5 @@ module.exports = {
|
|
|
227
253
|
buildAgentConfig,
|
|
228
254
|
windowsProvisionCommands,
|
|
229
255
|
linuxRunnerInstallCommand,
|
|
256
|
+
majorMinor,
|
|
230
257
|
};
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
"$schema": "./examples-manifest.schema.json",
|
|
3
3
|
"examples": {
|
|
4
4
|
"assert.test.mjs": {
|
|
5
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
6
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
7
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
8
|
-
"lastUpdated": "2026-05-
|
|
5
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a1640e572fbc49ea25d679b",
|
|
6
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a164876cdb57a637d2faabd?share=P6veCnmKhjRh1lJK7aMx4g",
|
|
7
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a164876cdb57a637d2faabd?share=P6veCnmKhjRh1lJK7aMx4g&embed=true",
|
|
8
|
+
"lastUpdated": "2026-05-27T01:27:24.420Z"
|
|
9
9
|
},
|
|
10
10
|
"drag-and-drop.test.mjs": {
|
|
11
11
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62b42fc0ac3cc632a918b",
|
|
12
12
|
"lastUpdated": "2026-03-03T00:32:25.275Z"
|
|
13
13
|
},
|
|
14
14
|
"exec-pwsh.test.mjs": {
|
|
15
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
16
|
-
"lastUpdated": "2026-05-
|
|
15
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16400472fbc49ea25d6715",
|
|
16
|
+
"lastUpdated": "2026-05-27T01:05:05.688Z"
|
|
17
17
|
},
|
|
18
18
|
"match-image.test.mjs": {
|
|
19
19
|
"url": "https://console-test.testdriver.ai/runs/69c8738614b73310c7839412/69c8738c14b73310c783941d",
|
|
@@ -24,92 +24,92 @@
|
|
|
24
24
|
"lastUpdated": "2026-03-03T00:32:25.282Z"
|
|
25
25
|
},
|
|
26
26
|
"hover-text-with-description.test.mjs": {
|
|
27
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
28
|
-
"lastUpdated": "2026-05-
|
|
27
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16401b72fbc49ea25d672e",
|
|
28
|
+
"lastUpdated": "2026-05-27T00:51:38.967Z"
|
|
29
29
|
},
|
|
30
30
|
"windows-installer.test.mjs": {
|
|
31
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
32
|
-
"lastUpdated": "2026-05-
|
|
31
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16404872fbc49ea25d6770",
|
|
32
|
+
"lastUpdated": "2026-05-27T01:06:16.047Z"
|
|
33
33
|
},
|
|
34
34
|
"exec-output.test.mjs": {
|
|
35
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
36
|
-
"lastUpdated": "2026-05-
|
|
35
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16404a72fbc49ea25d6773",
|
|
36
|
+
"lastUpdated": "2026-05-27T01:06:17.437Z"
|
|
37
37
|
},
|
|
38
38
|
"chrome-extension.test.mjs": {
|
|
39
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
40
|
-
"lastUpdated": "2026-05-
|
|
39
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16400272fbc49ea25d6713",
|
|
40
|
+
"lastUpdated": "2026-05-27T00:58:03.997Z"
|
|
41
41
|
},
|
|
42
42
|
"launch-vscode-linux.test.mjs": {
|
|
43
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
44
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
45
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
46
|
-
"lastUpdated": "2026-05-
|
|
43
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16403372fbc49ea25d6754",
|
|
44
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a16461acdb57a637d2faaad?share=FN1SuaLYCODCJGkQQDUsQ",
|
|
45
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a16461acdb57a637d2faaad?share=FN1SuaLYCODCJGkQQDUsQ&embed=true",
|
|
46
|
+
"lastUpdated": "2026-05-27T01:17:20.854Z"
|
|
47
47
|
},
|
|
48
48
|
"hover-image.test.mjs": {
|
|
49
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
50
|
-
"lastUpdated": "2026-05-
|
|
49
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16406072fbc49ea25d6784",
|
|
50
|
+
"lastUpdated": "2026-05-27T00:59:35.750Z"
|
|
51
51
|
},
|
|
52
52
|
"installer.test.mjs": {
|
|
53
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
54
|
-
"lastUpdated": "2026-05-
|
|
53
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16408272fbc49ea25d6790",
|
|
54
|
+
"lastUpdated": "2026-05-27T00:53:10.678Z"
|
|
55
55
|
},
|
|
56
56
|
"type.test.mjs": {
|
|
57
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
58
|
-
"lastUpdated": "2026-05-
|
|
57
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a1640b772fbc49ea25d6799",
|
|
58
|
+
"lastUpdated": "2026-05-27T01:01:05.252Z"
|
|
59
59
|
},
|
|
60
60
|
"press-keys.test.mjs": {
|
|
61
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
62
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
63
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
64
|
-
"lastUpdated": "2026-05-
|
|
61
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a1640cf72fbc49ea25d679a",
|
|
62
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a164834cdb57a637d2faabb?share=shwxxjLJAs6ja39RQGXcTA",
|
|
63
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a164834cdb57a637d2faabb?share=shwxxjLJAs6ja39RQGXcTA&embed=true",
|
|
64
|
+
"lastUpdated": "2026-05-27T01:26:18.025Z"
|
|
65
65
|
},
|
|
66
66
|
"scroll-keyboard.test.mjs": {
|
|
67
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
68
|
-
"lastUpdated": "2026-05-
|
|
67
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16411072fbc49ea25d679d",
|
|
68
|
+
"lastUpdated": "2026-05-27T01:09:42.258Z"
|
|
69
69
|
},
|
|
70
70
|
"scroll.test.mjs": {
|
|
71
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
72
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
73
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
74
|
-
"lastUpdated": "2026-05-
|
|
71
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16412b72fbc49ea25d67a1",
|
|
72
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a1649b84a4688499f88ea5d?share=gCsly4DGt4iQxlIjhHiceg",
|
|
73
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a1649b84a4688499f88ea5d?share=gCsly4DGt4iQxlIjhHiceg&embed=true",
|
|
74
|
+
"lastUpdated": "2026-05-27T01:32:46.425Z"
|
|
75
75
|
},
|
|
76
76
|
"scroll-until-image.test.mjs": {
|
|
77
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
78
|
-
"lastUpdated": "2026-05-
|
|
77
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16411272fbc49ea25d679e",
|
|
78
|
+
"lastUpdated": "2026-05-27T00:55:46.226Z"
|
|
79
79
|
},
|
|
80
80
|
"prompt.test.mjs": {
|
|
81
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
82
|
-
"lastUpdated": "2026-05-
|
|
81
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16411372fbc49ea25d679f",
|
|
82
|
+
"lastUpdated": "2026-05-27T01:09:45.225Z"
|
|
83
83
|
},
|
|
84
84
|
"focus-window.test.mjs": {
|
|
85
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
86
|
-
"lastUpdated": "2026-05-
|
|
85
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16411472fbc49ea25d67a0",
|
|
86
|
+
"lastUpdated": "2026-05-27T00:55:49.071Z"
|
|
87
87
|
},
|
|
88
88
|
"captcha-api.test.mjs": {
|
|
89
89
|
"url": "https://console.testdriver.ai/runs/698f7df69e27ce1528d7d087/698f7fb0d3b320ad547d9d44",
|
|
90
90
|
"lastUpdated": "2026-02-13T19:55:05.951Z"
|
|
91
91
|
},
|
|
92
92
|
"element-not-found.test.mjs": {
|
|
93
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
94
|
-
"lastUpdated": "2026-05-
|
|
93
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16414272fbc49ea25d67a2",
|
|
94
|
+
"lastUpdated": "2026-05-27T01:10:31.738Z"
|
|
95
95
|
},
|
|
96
96
|
"formatted-logging.test.mjs": {
|
|
97
97
|
"url": "https://console-test.testdriver.ai/runs/69c8738614b73310c7839412/69c873a714b73310c7839450",
|
|
98
98
|
"lastUpdated": "2026-03-29T00:36:10.628Z"
|
|
99
99
|
},
|
|
100
100
|
"hover-text.test.mjs": {
|
|
101
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
102
|
-
"lastUpdated": "2026-05-
|
|
101
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16417072fbc49ea25d67a4",
|
|
102
|
+
"lastUpdated": "2026-05-27T00:57:20.040Z"
|
|
103
103
|
},
|
|
104
104
|
"no-provision.test.mjs": {
|
|
105
105
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62b7706a177a05bccd1cf",
|
|
106
106
|
"lastUpdated": "2026-03-03T00:32:25.279Z"
|
|
107
107
|
},
|
|
108
108
|
"ai.test.mjs": {
|
|
109
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
110
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
111
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
112
|
-
"lastUpdated": "2026-05-
|
|
109
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16415872fbc49ea25d67a3",
|
|
110
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a164a834a4688499f88ea61?share=zG4dSiv1EBheV2pYxjSAA",
|
|
111
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a164a834a4688499f88ea61?share=zG4dSiv1EBheV2pYxjSAA&embed=true",
|
|
112
|
+
"lastUpdated": "2026-05-27T01:36:10.091Z"
|
|
113
113
|
},
|
|
114
114
|
"popup-loading.test.mjs": {
|
|
115
115
|
"url": "https://console.testdriver.ai/runs/698bc89f7140c3fa7daaca8d/698bca7f7140c3fa7daacbf7",
|
|
@@ -144,12 +144,12 @@
|
|
|
144
144
|
"lastUpdated": "2026-02-13T19:55:05.953Z"
|
|
145
145
|
},
|
|
146
146
|
"findall-coffee-icons.test.mjs": {
|
|
147
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
148
|
-
"lastUpdated": "2026-05-
|
|
147
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a1640fb72fbc49ea25d679c",
|
|
148
|
+
"lastUpdated": "2026-05-27T01:02:17.471Z"
|
|
149
149
|
},
|
|
150
150
|
"parse.test.mjs": {
|
|
151
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
152
|
-
"lastUpdated": "2026-05-
|
|
151
|
+
"url": "https://console-test.testdriver.ai/runs/6a163feb72fbc49ea25d66f1/6a16418572fbc49ea25d67a5",
|
|
152
|
+
"lastUpdated": "2026-05-27T01:11:39.542Z"
|
|
153
153
|
},
|
|
154
154
|
"flake-diffthreshold-001.test.mjs": {
|
|
155
155
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62bcafc0ac3cc632a91aa",
|
package/docs/v7/examples/ai.mdx
CHANGED
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* ai.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a164a834a4688499f88ea61?share=zG4dSiv1EBheV2pYxjSAA&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* assert.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a164876cdb57a637d2faabd?share=P6veCnmKhjRh1lJK7aMx4g&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* chrome-extension.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16400272fbc49ea25d6713/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -75,18 +75,35 @@ describe("Chrome Extension Test", () => {
|
|
|
75
75
|
// The hello-world extension adds a puzzle piece icon to the toolbar
|
|
76
76
|
// When clicked, it shows a popup with "Hello Extensions"
|
|
77
77
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
// Retry opening the extension popup and verifying it up to 3 times
|
|
79
|
+
let popupResult;
|
|
80
|
+
let lastError;
|
|
81
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
82
|
+
try {
|
|
83
|
+
// Click on the extensions button (puzzle piece icon) in Chrome toolbar
|
|
84
|
+
const extensionsButton = await testdriver.find("The extensions button in the Chrome toolbar", {zoom: true, verify: true, timeout: 10000});
|
|
85
|
+
await extensionsButton.click();
|
|
86
|
+
|
|
87
|
+
// Look for the hello world extension in the extensions menu
|
|
88
|
+
const helloExtension = await testdriver.find("Hello Extensions extension in the extensions dropdown", {zoom: true, verify: true, timeout: 10000});
|
|
89
|
+
await helloExtension.click();
|
|
90
|
+
|
|
91
|
+
await testdriver.wait(2000); // wait for the popup to open
|
|
92
|
+
|
|
93
|
+
// Verify the extension popup shows "Hello Extensions" text
|
|
94
|
+
popupResult = await testdriver.assert("a popup shows with the text 'Hello Extensions'");
|
|
95
|
+
if (popupResult) break;
|
|
96
|
+
} catch (err) {
|
|
97
|
+
lastError = err;
|
|
98
|
+
console.log(`Attempt ${attempt} failed:`, err.message);
|
|
99
|
+
}
|
|
100
|
+
if (attempt < 3) {
|
|
101
|
+
// Dismiss any open popup/menu before retrying
|
|
102
|
+
await testdriver.pressKeys(["escape"]);
|
|
103
|
+
await testdriver.wait(1000);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!popupResult && lastError) throw lastError;
|
|
90
107
|
expect(popupResult).toBeTruthy();
|
|
91
108
|
});
|
|
92
109
|
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* element-not-found.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16414272fbc49ea25d67a2/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* findall-coffee-icons.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a1640fb72fbc49ea25d679c/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* hover-image.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16406072fbc49ea25d6784/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* hover-text-with-description.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16401b72fbc49ea25d672e/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* hover-text.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16417072fbc49ea25d67a4/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* installer.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16408272fbc49ea25d6790/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* launch-vscode-linux.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a16461acdb57a637d2faaad?share=FN1SuaLYCODCJGkQQDUsQ&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* parse.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16418572fbc49ea25d67a5/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* press-keys.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a164834cdb57a637d2faabb?share=shwxxjLJAs6ja39RQGXcTA&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* scroll-keyboard.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a16411072fbc49ea25d679d/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* scroll.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a1649b84a4688499f88ea5d?share=gCsly4DGt4iQxlIjhHiceg&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* type.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a1640b772fbc49ea25d6799/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -52,18 +52,35 @@ describe("Chrome Extension Test", () => {
|
|
|
52
52
|
// The hello-world extension adds a puzzle piece icon to the toolbar
|
|
53
53
|
// When clicked, it shows a popup with "Hello Extensions"
|
|
54
54
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
// Retry opening the extension popup and verifying it up to 3 times
|
|
56
|
+
let popupResult;
|
|
57
|
+
let lastError;
|
|
58
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
59
|
+
try {
|
|
60
|
+
// Click on the extensions button (puzzle piece icon) in Chrome toolbar
|
|
61
|
+
const extensionsButton = await testdriver.find("The extensions button in the Chrome toolbar", {zoom: true, verify: true, timeout: 10000});
|
|
62
|
+
await extensionsButton.click();
|
|
63
|
+
|
|
64
|
+
// Look for the hello world extension in the extensions menu
|
|
65
|
+
const helloExtension = await testdriver.find("Hello Extensions extension in the extensions dropdown", {zoom: true, verify: true, timeout: 10000});
|
|
66
|
+
await helloExtension.click();
|
|
67
|
+
|
|
68
|
+
await testdriver.wait(2000); // wait for the popup to open
|
|
69
|
+
|
|
70
|
+
// Verify the extension popup shows "Hello Extensions" text
|
|
71
|
+
popupResult = await testdriver.assert("a popup shows with the text 'Hello Extensions'");
|
|
72
|
+
if (popupResult) break;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
lastError = err;
|
|
75
|
+
console.log(`Attempt ${attempt} failed:`, err.message);
|
|
76
|
+
}
|
|
77
|
+
if (attempt < 3) {
|
|
78
|
+
// Dismiss any open popup/menu before retrying
|
|
79
|
+
await testdriver.pressKeys(["escape"]);
|
|
80
|
+
await testdriver.wait(1000);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!popupResult && lastError) throw lastError;
|
|
67
84
|
expect(popupResult).toBeTruthy();
|
|
68
85
|
});
|
|
69
86
|
|
package/lib/core/Dashcam.js
CHANGED
|
@@ -174,6 +174,24 @@ class Dashcam {
|
|
|
174
174
|
this._log("debug", "Auth output:", authOutput);
|
|
175
175
|
} else {
|
|
176
176
|
// Linux/Mac authentication with TD_API_ROOT
|
|
177
|
+
|
|
178
|
+
// Workaround for dashcam <1.5.0: webLogsDaemon.js writes its state to a
|
|
179
|
+
// `.dashcam` directory relative to process.cwd(). When launched by the
|
|
180
|
+
// runner, cwd is /usr/lib/node_modules/@testdriverai/runner (root-owned),
|
|
181
|
+
// so the daemon can't mkdir its state dir as user `user` and silently
|
|
182
|
+
// dies — recordings never start. Pre-create world-writable .dashcam dirs
|
|
183
|
+
// at both the current cwd and the known global-install path so the
|
|
184
|
+
// daemon survives regardless of which path dashcam ends up using.
|
|
185
|
+
// TODO: remove once dashcam >=1.5.0 (which uses $HOME) is bundled.
|
|
186
|
+
await this.client.exec(
|
|
187
|
+
shell,
|
|
188
|
+
`sudo mkdir -p "$(pwd)/.dashcam" /usr/lib/node_modules/@testdriverai/runner/.dashcam 2>/dev/null; ` +
|
|
189
|
+
`sudo chmod 0777 "$(pwd)/.dashcam" /usr/lib/node_modules/@testdriverai/runner/.dashcam 2>/dev/null; ` +
|
|
190
|
+
`true`,
|
|
191
|
+
10000,
|
|
192
|
+
process.env.TD_DEBUG == "true" ? false : true,
|
|
193
|
+
);
|
|
194
|
+
|
|
177
195
|
const authOutput = await this.client.exec(
|
|
178
196
|
shell,
|
|
179
197
|
`TD_API_ROOT="${apiRoot}" dashcam auth ${key}`,
|