testdriverai 7.8.0 → 7.9.0-test.1

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 (55) hide show
  1. package/agent/index.js +12 -0
  2. package/agent/lib/http.js +21 -3
  3. package/agent/lib/logger.js +15 -0
  4. package/agent/lib/provision-commands.js +176 -0
  5. package/agent/lib/sandbox.js +667 -118
  6. package/agent/lib/sdk.js +1 -20
  7. package/ai/skills/testdriver-find/SKILL.md +14 -20
  8. package/docs/_data/examples-manifest.json +46 -46
  9. package/docs/_scripts/extract-example-urls.js +67 -72
  10. package/docs/docs.json +2 -1
  11. package/docs/v7/examples/ai.mdx +1 -1
  12. package/docs/v7/examples/assert.mdx +1 -1
  13. package/docs/v7/examples/captcha-api.mdx +1 -1
  14. package/docs/v7/examples/chrome-extension.mdx +1 -1
  15. package/docs/v7/examples/drag-and-drop.mdx +1 -1
  16. package/docs/v7/examples/element-not-found.mdx +1 -1
  17. package/docs/v7/examples/exec-output.mdx +1 -1
  18. package/docs/v7/examples/exec-pwsh.mdx +1 -1
  19. package/docs/v7/examples/focus-window.mdx +1 -1
  20. package/docs/v7/examples/hover-image.mdx +1 -1
  21. package/docs/v7/examples/hover-text.mdx +1 -1
  22. package/docs/v7/examples/installer.mdx +1 -1
  23. package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
  24. package/docs/v7/examples/match-image.mdx +1 -1
  25. package/docs/v7/examples/press-keys.mdx +1 -1
  26. package/docs/v7/examples/scroll-keyboard.mdx +1 -1
  27. package/docs/v7/examples/scroll-until-image.mdx +1 -1
  28. package/docs/v7/examples/scroll-until-text.mdx +1 -1
  29. package/docs/v7/examples/scroll.mdx +1 -1
  30. package/docs/v7/examples/type.mdx +1 -1
  31. package/docs/v7/examples/windows-installer.mdx +1 -1
  32. package/docs/v7/find.mdx +14 -20
  33. package/docs/v7/test-results-json.mdx +258 -0
  34. package/examples/scroll-keyboard.test.mjs +1 -1
  35. package/examples/scroll.test.mjs +1 -12
  36. package/interfaces/vitest-plugin.mjs +167 -51
  37. package/lib/core/Dashcam.js +16 -22
  38. package/lib/environments.json +8 -4
  39. package/lib/github-comment.mjs +58 -40
  40. package/lib/init-project.js +5 -67
  41. package/lib/resolve-channel.js +39 -10
  42. package/lib/sentry.js +47 -23
  43. package/lib/vitest/hooks.mjs +117 -20
  44. package/manual/exec-stream-logs.test.mjs +25 -0
  45. package/mcp-server/dist/server.mjs +28 -8
  46. package/mcp-server/src/server.ts +31 -8
  47. package/package.json +2 -1
  48. package/sdk.d.ts +4 -0
  49. package/sdk.js +42 -12
  50. package/setup/aws/install-dev-runner.sh +79 -0
  51. package/setup/aws/spawn-runner.sh +165 -0
  52. package/test-sentry-span.js +35 -0
  53. package/vitest.config.mjs +7 -3
  54. package/vitest.runner.config.mjs +33 -0
  55. package/docs/v7/_drafts/core.mdx +0 -458
@@ -141,6 +141,171 @@ while :; do
141
141
  sleep 20
142
142
  done
143
143
 
144
+ # --- 4) Install/update runner ---
145
+ echo "Installing runner..."
146
+
147
+ # Determine environment and version
148
+ TD_CHANNEL="${TD_CHANNEL:-stable}"
149
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
150
+ SDK_PKG_JSON="${SCRIPT_DIR}/../../../sdk/package.json"
151
+ RUNNER_DIR="${SCRIPT_DIR}/../../../runner"
152
+
153
+ if [ -f "$SDK_PKG_JSON" ]; then
154
+ RUNNER_VERSION=$(jq -r '.version' "$SDK_PKG_JSON")
155
+ echo "Runner version from SDK: $RUNNER_VERSION"
156
+ else
157
+ RUNNER_VERSION="$TD_CHANNEL"
158
+ echo "SDK package.json not found, using env tag: $RUNNER_VERSION"
159
+ fi
160
+
161
+ if [ "$TD_CHANNEL" = "dev" ]; then
162
+ echo "Dev mode: packing and uploading local runner to S3..."
163
+
164
+ # Pack local runner
165
+ TMPDIR=$(mktemp -d)
166
+ pushd "$RUNNER_DIR" > /dev/null
167
+ npm pack --pack-destination "$TMPDIR" > /dev/null 2>&1
168
+ TARBALL=$(ls "$TMPDIR"/*.tgz | head -1)
169
+ popd > /dev/null
170
+
171
+ # Upload to S3
172
+ S3_BUCKET="${AWS_BUCKET_IMAGE_TRANSFER:-v7-transfer}"
173
+ S3_KEY="runner-dev/$(date +%s)-$(openssl rand -hex 4)/runner.tgz"
174
+ aws s3 cp "$TARBALL" "s3://${S3_BUCKET}/${S3_KEY}" --region "$AWS_REGION"
175
+
176
+ # Generate presigned URL (15 min)
177
+ DOWNLOAD_URL=$(aws s3 presign "s3://${S3_BUCKET}/${S3_KEY}" --expires-in 900 --region "$AWS_REGION")
178
+ rm -rf "$TMPDIR"
179
+
180
+ # Build SSM parameters JSON in a temp file to avoid shell escaping issues with URL
181
+ PARAMS_FILE=$(mktemp)
182
+ cat > "$PARAMS_FILE" << 'PARAMS_EOF'
183
+ {
184
+ "commands": [
185
+ "Write-Host '=== Starting runner dev install ==='",
186
+ "Write-Host 'Stopping existing runner processes...'",
187
+ "Stop-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
188
+ "Stop-Process -Name node -Force -ErrorAction SilentlyContinue",
189
+ "Start-Sleep -Seconds 2",
190
+ "Write-Host 'Current runner version:'",
191
+ "Get-Content 'C:\\testdriver\\sandbox-agent\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
192
+ "Set-Location 'C:\\testdriver\\sandbox-agent'",
193
+ "Write-Host 'Dev mode: downloading runner from S3...'",
194
+ "$tarball = 'C:\\Windows\\Temp\\runner-dev.tgz'",
195
+ PARAMS_EOF
196
+
197
+ # Add the URL line with proper JSON escaping
198
+ echo " \"Invoke-WebRequest -Uri '$(echo "$DOWNLOAD_URL" | sed 's/"/\\"/g')' -OutFile \$tarball\"," >> "$PARAMS_FILE"
199
+
200
+ cat >> "$PARAMS_FILE" << 'PARAMS_EOF'
201
+ "Write-Host 'Downloaded tarball size:'",
202
+ "(Get-Item $tarball).Length",
203
+ "Write-Host 'Extracting runner...'",
204
+ "tar -xzf $tarball -C 'C:\\Windows\\Temp'",
205
+ "Write-Host 'Extracted package contents:'",
206
+ "Get-ChildItem 'C:\\Windows\\Temp\\package' -Recurse | Select-Object FullName",
207
+ "Write-Host 'New runner version in package:'",
208
+ "Get-Content 'C:\\Windows\\Temp\\package\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
209
+ "Write-Host 'Clearing old lib folder...'",
210
+ "Remove-Item 'C:\\testdriver\\sandbox-agent\\lib' -Recurse -Force -ErrorAction SilentlyContinue",
211
+ "Write-Host 'Copying files to sandbox-agent...'",
212
+ "xcopy 'C:\\Windows\\Temp\\package\\*' 'C:\\testdriver\\sandbox-agent\\' /E /Y /I",
213
+ "Write-Host 'Files after copy:'",
214
+ "Get-ChildItem 'C:\\testdriver\\sandbox-agent' | Select-Object Name",
215
+ "Remove-Item 'C:\\Windows\\Temp\\package' -Recurse -Force -ErrorAction SilentlyContinue",
216
+ "Remove-Item $tarball -Force -ErrorAction SilentlyContinue",
217
+ "Write-Host 'Runner version after copy:'",
218
+ "Get-Content 'C:\\testdriver\\sandbox-agent\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
219
+ "Write-Host 'Installing npm dependencies...'",
220
+ "npm install --omit=dev 2>&1 | Write-Host",
221
+ "Write-Host 'Final verification - ably-service.js exists:'",
222
+ "Test-Path 'C:\\testdriver\\sandbox-agent\\lib\\ably-service.js'",
223
+ "Write-Host 'Restarting RunTestDriverAgent scheduled task...'",
224
+ "Start-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
225
+ "Write-Host '=== Runner install complete (dev) ==='"
226
+ ]
227
+ }
228
+ PARAMS_EOF
229
+
230
+ echo "Sending SSM command to download and install runner from S3..."
231
+ INSTALL_CMD=$(aws ssm send-command \
232
+ --region "$AWS_REGION" \
233
+ --instance-ids "$INSTANCE_ID" \
234
+ --document-name "AWS-RunPowerShellScript" \
235
+ --parameters "file://$PARAMS_FILE" \
236
+ --timeout-seconds 180 \
237
+ --output json)
238
+ rm -f "$PARAMS_FILE"
239
+ else
240
+ echo "Installing @testdriverai/runner@${RUNNER_VERSION} via npm pack + extract..."
241
+
242
+ # Build SSM parameters JSON in a temp file (same approach as dev mode)
243
+ PARAMS_FILE=$(mktemp)
244
+ cat > "$PARAMS_FILE" << PARAMS_EOF
245
+ {
246
+ "commands": [
247
+ "Write-Host '=== Starting runner install (npm pack) ==='",
248
+ "Write-Host 'Stopping existing runner processes...'",
249
+ "Stop-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
250
+ "Stop-Process -Name node -Force -ErrorAction SilentlyContinue",
251
+ "Start-Sleep -Seconds 2",
252
+ "Write-Host 'Current runner version:'",
253
+ "Get-Content 'C:\\\\testdriver\\\\sandbox-agent\\\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
254
+ "Set-Location 'C:\\\\Windows\\\\Temp'",
255
+ "Write-Host 'Downloading @testdriverai/runner@${RUNNER_VERSION} via npm pack...'",
256
+ "npm pack @testdriverai/runner@${RUNNER_VERSION} 2>&1 | Write-Host",
257
+ "\$tarball = (Get-ChildItem 'C:\\\\Windows\\\\Temp\\\\testdriverai-runner-*.tgz' | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName",
258
+ "Write-Host \"Downloaded tarball: \$tarball\"",
259
+ "Write-Host 'Extracting runner...'",
260
+ "tar -xzf \$tarball -C 'C:\\\\Windows\\\\Temp'",
261
+ "Write-Host 'New runner version in package:'",
262
+ "Get-Content 'C:\\\\Windows\\\\Temp\\\\package\\\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
263
+ "Write-Host 'Clearing old lib folder...'",
264
+ "Remove-Item 'C:\\\\testdriver\\\\sandbox-agent\\\\lib' -Recurse -Force -ErrorAction SilentlyContinue",
265
+ "Write-Host 'Copying files to sandbox-agent...'",
266
+ "xcopy 'C:\\\\Windows\\\\Temp\\\\package\\\\*' 'C:\\\\testdriver\\\\sandbox-agent\\\\' /E /Y /I",
267
+ "Write-Host 'Runner version after copy:'",
268
+ "Get-Content 'C:\\\\testdriver\\\\sandbox-agent\\\\package.json' | ConvertFrom-Json | Select-Object -ExpandProperty version",
269
+ "Remove-Item 'C:\\\\Windows\\\\Temp\\\\package' -Recurse -Force -ErrorAction SilentlyContinue",
270
+ "Remove-Item \$tarball -Force -ErrorAction SilentlyContinue",
271
+ "Set-Location 'C:\\\\testdriver\\\\sandbox-agent'",
272
+ "Write-Host 'Installing npm dependencies...'",
273
+ "npm install --omit=dev 2>&1 | Write-Host",
274
+ "Write-Host 'Restarting RunTestDriverAgent scheduled task...'",
275
+ "Start-ScheduledTask -TaskName RunTestDriverAgent -ErrorAction SilentlyContinue",
276
+ "Write-Host '=== Runner install complete (npm pack) ==='"
277
+ ]
278
+ }
279
+ PARAMS_EOF
280
+
281
+ INSTALL_CMD=$(aws ssm send-command \
282
+ --region "$AWS_REGION" \
283
+ --instance-ids "$INSTANCE_ID" \
284
+ --document-name "AWS-RunPowerShellScript" \
285
+ --parameters "file://$PARAMS_FILE" \
286
+ --timeout-seconds 180 \
287
+ --output json)
288
+ rm -f "$PARAMS_FILE"
289
+ fi
290
+
291
+ INSTALL_CMD_ID=$(jq -r '.Command.CommandId' <<<"$INSTALL_CMD")
292
+ echo "Runner install command sent (Command ID: $INSTALL_CMD_ID)"
293
+
294
+ # Wait for install to complete
295
+ echo "Waiting for runner install to complete..."
296
+ if aws ssm wait command-executed --region "$AWS_REGION" --command-id "$INSTALL_CMD_ID" --instance-id "$INSTANCE_ID" 2>/dev/null; then
297
+ echo "✓ Runner install succeeded"
298
+ else
299
+ INSTALL_STATUS=$(aws ssm get-command-invocation \
300
+ --region "$AWS_REGION" \
301
+ --command-id "$INSTALL_CMD_ID" \
302
+ --instance-id "$INSTANCE_ID" \
303
+ --output json 2>/dev/null || echo '{}')
304
+ echo "⚠ Runner install status: $(jq -r '.Status // "Unknown"' <<<"$INSTALL_STATUS")"
305
+ echo "Output: $(jq -r '.StandardOutputContent // "No output"' <<<"$INSTALL_STATUS" | head -20)"
306
+ echo "Errors: $(jq -r '.StandardErrorContent // "No errors"' <<<"$INSTALL_STATUS" | head -10)"
307
+ fi
308
+
144
309
  echo "Getting Public IP..."
145
310
 
146
311
  # --- 5) Get instance Public IP ---
@@ -0,0 +1,35 @@
1
+ const Sentry = require('@sentry/node');
2
+ const crypto = require('crypto');
3
+
4
+ Sentry.init({ dsn: 'https://test@sentry.io/123', tracesSampleRate: 1.0 });
5
+
6
+ const sessionId = 'test-session-123';
7
+ const traceId = crypto.createHash('md5').update(sessionId).digest('hex');
8
+ console.log('expected traceId:', traceId);
9
+
10
+ const sentryTraceHeader = traceId + '-' + crypto.randomBytes(8).toString('hex') + '-1';
11
+ const baggageHeader = 'sentry-trace_id=' + traceId + ',sentry-sampled=true';
12
+
13
+ // Approach: Use continueTrace + startInactiveSpan for the root, then rely on scope
14
+ // for getTraceData propagation
15
+ Sentry.continueTrace(
16
+ { sentryTrace: sentryTraceHeader, baggage: baggageHeader },
17
+ () => {
18
+ // This sets propagation context on the current scope
19
+ const rootSpan = Sentry.startInactiveSpan({ name: 'sdk.session', op: 'session', forceTransaction: true });
20
+
21
+ // After continueTrace returns, check if getTraceData still uses the right traceId
22
+ const td = Sentry.getTraceData();
23
+ console.log('after continueTrace getTraceData:', JSON.stringify(td));
24
+ console.log('traceId matches:', td['sentry-trace'] && td['sentry-trace'].startsWith(traceId));
25
+
26
+ // Simulate async: do a child span later
27
+ setTimeout(() => {
28
+ const td2 = Sentry.getTraceData();
29
+ console.log('async getTraceData:', JSON.stringify(td2));
30
+ console.log('async traceId matches:', td2['sentry-trace'] && td2['sentry-trace'].startsWith(traceId));
31
+ rootSpan.end();
32
+ process.exit(0);
33
+ }, 100);
34
+ }
35
+ );
package/vitest.config.mjs CHANGED
@@ -14,11 +14,15 @@ const setupFiles = [
14
14
 
15
15
  const sharedTestConfig = {
16
16
  retry: 0,
17
- testTimeout: 900000,
18
- hookTimeout: 900000,
17
+ testTimeout: 480000,
18
+ hookTimeout: 480000,
19
19
  maxConcurrency: 100,
20
20
  disableConsoleIntercept: false,
21
21
  silent: false,
22
+ // Use child-process forks so each test FILE gets a completely clean
23
+ // Node.js process — no shared Ably connections, module-level singletons,
24
+ // or Sentry globals bleeding between files.
25
+ pool: "forks",
22
26
  reporters: [
23
27
  "verbose",
24
28
  TestDriver()
@@ -31,7 +35,7 @@ const sharedTestConfig = {
31
35
  // Uses: environments.json (URLs) + envs/{env}.env (overlay) + fixtures (API keys)
32
36
  // TD_PLAN selects which plan's API key to use (default: enterprise)
33
37
  const plan = process.env.TD_PLAN || "enterprise";
34
- const defaultEnv = process.env.TD_ENV || "dev";
38
+ const defaultEnv = process.env.TD_CHANNEL || "dev";
35
39
  const environments = getEnvironmentNames();
36
40
 
37
41
  // Apply default env to the main process so the reporter/plugin picks it up
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Vitest config for runner/packer tests.
3
+ * Lives under sdk/ so vitest resolves from sdk/node_modules,
4
+ * but uses shared/resolve-env.js for environment variable loading.
5
+ */
6
+ import { defineConfig } from "vitest/config";
7
+ import { createRequire } from "module";
8
+ import { dirname, resolve } from "path";
9
+ import { fileURLToPath } from "url";
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const monoRoot = resolve(__dirname, "..");
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const { resolveEnv } = require("../shared/resolve-env");
16
+
17
+ const plan = process.env.TD_PLAN || "enterprise";
18
+ const env = process.env.TD_CHANNEL || "dev";
19
+ const resolved = resolveEnv(env, plan);
20
+
21
+ // Apply to the main process so test code sees the vars immediately
22
+ Object.assign(process.env, resolved);
23
+
24
+ export default defineConfig({
25
+ test: {
26
+ root: monoRoot,
27
+ testTimeout: 900_000, // 15 min per test
28
+ hookTimeout: 2_400_000, // 40 min for beforeAll (AMI build + spawn)
29
+ reporters: ["default"],
30
+ include: ["runner/packer/test/**/*.test.mjs"],
31
+ env: resolved,
32
+ },
33
+ });