testdriverai 7.5.26 → 7.6.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/sdk.js CHANGED
@@ -1402,7 +1402,7 @@ function normalizeRedrawOptions(opts) {
1402
1402
  * @typedef {'up' | 'down' | 'left' | 'right'} ScrollDirection
1403
1403
  * @typedef {'keyboard' | 'mouse'} ScrollMethod
1404
1404
  * @typedef {'ai' | 'turbo'} TextMatchMethod
1405
- * @typedef {'js' | 'pwsh'} ExecLanguage
1405
+ * @typedef {'sh' | 'pwsh'} ExecLanguage
1406
1406
  * @typedef {'\\t' | '\n' | '\r' | ' ' | '!' | '"' | '#' | '$' | '%' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | '-' | '.' | '/' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '[' | '\\' | ']' | '^' | '_' | '`' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | '{' | '|' | '}' | '~' | 'accept' | 'add' | 'alt' | 'altleft' | 'altright' | 'apps' | 'backspace' | 'browserback' | 'browserfavorites' | 'browserforward' | 'browserhome' | 'browserrefresh' | 'browsersearch' | 'browserstop' | 'capslock' | 'clear' | 'convert' | 'ctrl' | 'ctrlleft' | 'ctrlright' | 'decimal' | 'del' | 'delete' | 'divide' | 'down' | 'end' | 'enter' | 'esc' | 'escape' | 'execute' | 'f1' | 'f10' | 'f11' | 'f12' | 'f13' | 'f14' | 'f15' | 'f16' | 'f17' | 'f18' | 'f19' | 'f2' | 'f20' | 'f21' | 'f22' | 'f23' | 'f24' | 'f3' | 'f4' | 'f5' | 'f6' | 'f7' | 'f8' | 'f9' | 'final' | 'fn' | 'hanguel' | 'hangul' | 'hanja' | 'help' | 'home' | 'insert' | 'junja' | 'kana' | 'kanji' | 'launchapp1' | 'launchapp2' | 'launchmail' | 'launchmediaselect' | 'left' | 'modechange' | 'multiply' | 'nexttrack' | 'nonconvert' | 'num0' | 'num1' | 'num2' | 'num3' | 'num4' | 'num5' | 'num6' | 'num7' | 'num8' | 'num9' | 'numlock' | 'pagedown' | 'pageup' | 'pause' | 'pgdn' | 'pgup' | 'playpause' | 'prevtrack' | 'print' | 'printscreen' | 'prntscrn' | 'prtsc' | 'prtscr' | 'return' | 'right' | 'scrolllock' | 'select' | 'separator' | 'shift' | 'shiftleft' | 'shiftright' | 'sleep' | 'space' | 'stop' | 'subtract' | 'tab' | 'up' | 'volumedown' | 'volumemute' | 'volumeup' | 'win' | 'winleft' | 'winright' | 'yen' | 'command' | 'option' | 'optionleft' | 'optionright'} KeyboardKey
1407
1407
  */
1408
1408
 
@@ -1910,7 +1910,7 @@ class TestDriverSDK {
1910
1910
  // Add web log tracking with domain wildcard pattern, then start dashcam
1911
1911
  if (this.dashcamEnabled) {
1912
1912
  const domainPattern = this._getUrlDomainPattern(url);
1913
- // await this.dashcam.addWebLog(domainPattern, "Web Logs");
1913
+ await this.dashcam.addWebLog(domainPattern, "Web Logs");
1914
1914
 
1915
1915
  // Start dashcam recording after logs are configured
1916
1916
  if (!(await this.dashcam.isRecording())) {
@@ -2477,7 +2477,7 @@ with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
2477
2477
  const pattern = this._provisionedChromeUrl
2478
2478
  ? this._getUrlDomainPattern(this._provisionedChromeUrl)
2479
2479
  : "**";
2480
- // await this.dashcam.addWebLog(pattern, "Web Logs");
2480
+ await this.dashcam.addWebLog(pattern, "Web Logs");
2481
2481
  }
2482
2482
 
2483
2483
  // Start recording if not already recording
@@ -2864,6 +2864,9 @@ CAPTCHA_SOLVER_EOF`,
2864
2864
  sandboxId: this.instance?.instanceId,
2865
2865
  });
2866
2866
 
2867
+ // Log environment info (non-blocking, skip on stable)
2868
+ this._logEnvironmentInfo();
2869
+
2867
2870
  return this.instance;
2868
2871
  }
2869
2872
 
@@ -2892,8 +2895,10 @@ CAPTCHA_SOLVER_EOF`,
2892
2895
 
2893
2896
  // Always close the sandbox WebSocket connection to clean up resources
2894
2897
  // This ensures we don't leave orphaned connections even if connect() failed
2898
+ // Must be awaited so presence.leave() completes before we return —
2899
+ // otherwise the concurrency counter on the API stays stale.
2895
2900
  if (this.sandbox && typeof this.sandbox.close === "function") {
2896
- this.sandbox.close();
2901
+ await this.sandbox.close();
2897
2902
  }
2898
2903
 
2899
2904
  // Remove all event listeners on the emitter to release references
@@ -3801,6 +3806,46 @@ CAPTCHA_SOLVER_EOF`,
3801
3806
  * Set up logging for the SDK
3802
3807
  * @private
3803
3808
  */
3809
+ /**
3810
+ * Log environment info (version, API URL, git commit) after connect.
3811
+ * Fires asynchronously so it never blocks the test.
3812
+ * Suppressed when the API reports the "stable" channel.
3813
+ * @private
3814
+ */
3815
+ _logEnvironmentInfo() {
3816
+ const apiRoot = this.config?.TD_API_ROOT || 'unknown';
3817
+ const sdkVersion = require('./package.json').version;
3818
+ const http = apiRoot.startsWith('https') ? require('https') : require('http');
3819
+
3820
+ const url = apiRoot + '/api/entrance/version';
3821
+ const req = http.get(url, { timeout: 5000 }, (res) => {
3822
+ let data = '';
3823
+ res.on('data', (chunk) => { data += chunk; });
3824
+ res.on('end', () => {
3825
+ try {
3826
+ const info = JSON.parse(data);
3827
+ if (info.channel === 'stable') return; // don't show on stable
3828
+ const commit = info.commit || 'unknown';
3829
+ const shortCommit = commit.substring(0, 7);
3830
+ const commitUrl = commit !== 'unknown'
3831
+ ? `https://github.com/testdriverai/mono/commit/${commit}`
3832
+ : null;
3833
+ const lines = [
3834
+ '',
3835
+ ` TestDriver SDK v${sdkVersion}`,
3836
+ ` API: ${apiRoot} (${info.channel || 'unknown'} v${info.version || '?'})`,
3837
+ commitUrl
3838
+ ? ` Commit: ${shortCommit} → ${commitUrl}`
3839
+ : ` Commit: ${shortCommit}`,
3840
+ '',
3841
+ ];
3842
+ console.log(lines.join('\n'));
3843
+ } catch (_) { /* ignore parse errors */ }
3844
+ });
3845
+ });
3846
+ req.on('error', () => { /* ignore network errors */ });
3847
+ }
3848
+
3804
3849
  _setupLogging() {
3805
3850
  // Track the last fatal error message to throw on exit
3806
3851
  let lastFatalError = null;
package/vitest.config.mjs CHANGED
@@ -1,5 +1,7 @@
1
1
  import TestDriver from "testdriverai/vitest";
2
2
  import { defineConfig } from "vitest/config";
3
+ import { readFileSync, existsSync } from "fs";
4
+ import { resolve } from "path";
3
5
 
4
6
  // Always include AWS setup - it will be a no-op unless TD_OS=windows
5
7
  // Note: dotenv is loaded automatically by the TestDriver SDK
@@ -8,19 +10,61 @@ const setupFiles = [
8
10
  "testdriverai/vitest/setup-aws"
9
11
  ];
10
12
 
13
+ const sharedTestConfig = {
14
+ retry: 0,
15
+ testTimeout: 900000,
16
+ hookTimeout: 900000,
17
+ maxConcurrency: 100,
18
+ disableConsoleIntercept: false,
19
+ silent: false,
20
+ reporters: [
21
+ "verbose",
22
+ TestDriver()
23
+ ],
24
+ setupFiles,
25
+ include: ["examples/**/*.test.mjs"],
26
+ };
27
+
28
+ // ── Parse a simple KEY=VALUE .env file ──────────────────────────────
29
+ function parseEnvFile(filePath) {
30
+ if (!existsSync(filePath)) return {};
31
+ const env = {};
32
+ for (const line of readFileSync(filePath, "utf-8").split("\n")) {
33
+ const trimmed = line.trim();
34
+ if (!trimmed || trimmed.startsWith("#")) continue;
35
+ const idx = trimmed.indexOf("=");
36
+ if (idx === -1) continue;
37
+ env[trimmed.slice(0, idx)] = trimmed.slice(idx + 1);
38
+ }
39
+ return env;
40
+ }
41
+
42
+ // ── Load base .env + per-environment overlay ────────────────────────
43
+ const monoRoot = resolve(import.meta.dirname, "..");
44
+ const baseEnv = parseEnvFile(resolve(monoRoot, ".env"));
45
+
46
+ const environments = ["dev", "test", "canary", "stable"];
47
+
48
+ function envForProject(envName) {
49
+ const overlay = parseEnvFile(resolve(monoRoot, "envs", `${envName}.env`));
50
+ return { ...baseEnv, ...overlay };
51
+ }
52
+
53
+ // ── If TD_ENV is set (e.g. from CLI), only run that environment ─────
54
+ // Usage: TD_ENV=dev vitest run
55
+ // TD_ENV=canary vitest run examples/assert.test.mjs
56
+ // vitest run --project dev
57
+ // vitest run --project canary --project stable
11
58
  export default defineConfig({
12
59
  test: {
13
- retry: 0,
14
- testTimeout: 900000,
15
- hookTimeout: 900000,
16
- maxConcurrency: 100,
17
- maxWorkers: 16,
18
- disableConsoleIntercept: false,
19
- silent: false,
20
- reporters: [
21
- "verbose",
22
- TestDriver()
23
- ],
24
- setupFiles,
60
+ ...sharedTestConfig,
61
+ env: envForProject(process.env.TD_ENV || "dev"),
62
+ projects: environments.map((envName) => ({
63
+ extends: true,
64
+ test: {
65
+ name: envName,
66
+ env: envForProject(envName),
67
+ },
68
+ })),
25
69
  },
26
70
  });