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.
- package/agent/index.js +12 -0
- package/agent/lib/http.js +21 -3
- package/agent/lib/logger.js +15 -0
- package/agent/lib/provision-commands.js +176 -0
- package/agent/lib/sandbox.js +667 -118
- package/agent/lib/sdk.js +1 -20
- package/ai/skills/testdriver-find/SKILL.md +14 -20
- package/docs/_data/examples-manifest.json +46 -46
- package/docs/_scripts/extract-example-urls.js +67 -72
- package/docs/docs.json +2 -1
- package/docs/v7/examples/ai.mdx +1 -1
- package/docs/v7/examples/assert.mdx +1 -1
- package/docs/v7/examples/captcha-api.mdx +1 -1
- package/docs/v7/examples/chrome-extension.mdx +1 -1
- package/docs/v7/examples/drag-and-drop.mdx +1 -1
- package/docs/v7/examples/element-not-found.mdx +1 -1
- package/docs/v7/examples/exec-output.mdx +1 -1
- package/docs/v7/examples/exec-pwsh.mdx +1 -1
- package/docs/v7/examples/focus-window.mdx +1 -1
- package/docs/v7/examples/hover-image.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/match-image.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-until-image.mdx +1 -1
- package/docs/v7/examples/scroll-until-text.mdx +1 -1
- package/docs/v7/examples/scroll.mdx +1 -1
- package/docs/v7/examples/type.mdx +1 -1
- package/docs/v7/examples/windows-installer.mdx +1 -1
- package/docs/v7/find.mdx +14 -20
- package/docs/v7/test-results-json.mdx +258 -0
- package/examples/scroll-keyboard.test.mjs +1 -1
- package/examples/scroll.test.mjs +1 -12
- package/interfaces/vitest-plugin.mjs +167 -51
- package/lib/core/Dashcam.js +16 -22
- package/lib/environments.json +8 -4
- package/lib/github-comment.mjs +58 -40
- package/lib/init-project.js +5 -67
- package/lib/resolve-channel.js +39 -10
- package/lib/sentry.js +47 -23
- package/lib/vitest/hooks.mjs +117 -20
- package/manual/exec-stream-logs.test.mjs +25 -0
- package/mcp-server/dist/server.mjs +28 -8
- package/mcp-server/src/server.ts +31 -8
- package/package.json +2 -1
- package/sdk.d.ts +4 -0
- package/sdk.js +42 -12
- package/setup/aws/install-dev-runner.sh +79 -0
- package/setup/aws/spawn-runner.sh +165 -0
- package/test-sentry-span.js +35 -0
- package/vitest.config.mjs +7 -3
- package/vitest.runner.config.mjs +33 -0
- 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:
|
|
18
|
-
hookTimeout:
|
|
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.
|
|
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
|
+
});
|