testdriverai 7.1.4 → 7.2.2
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/.github/workflows/acceptance.yaml +81 -0
- package/.github/workflows/publish.yaml +44 -0
- package/agent/index.js +18 -19
- package/agent/interface.js +4 -0
- package/agent/lib/commands.js +321 -121
- package/agent/lib/redraw.js +99 -39
- package/agent/lib/sandbox.js +98 -6
- package/agent/lib/sdk.js +25 -0
- package/agent/lib/system.js +2 -1
- package/agent/lib/validation.js +6 -6
- package/docs/docs.json +211 -101
- package/docs/snippets/tests/type-repeated-replay.mdx +1 -1
- package/docs/v7/_drafts/caching-selectors.mdx +24 -0
- package/docs/v7/api/act.mdx +1 -1
- package/docs/v7/api/assert.mdx +1 -1
- package/docs/v7/api/assertions.mdx +7 -7
- package/docs/v7/api/elements.mdx +78 -0
- package/docs/v7/api/find.mdx +38 -0
- package/docs/v7/api/focusApplication.mdx +2 -2
- package/docs/v7/api/hover.mdx +2 -2
- package/docs/v7/features/ai-native.mdx +57 -71
- package/docs/v7/features/application-logs.mdx +353 -0
- package/docs/v7/features/browser-logs.mdx +414 -0
- package/docs/v7/features/cache-management.mdx +402 -0
- package/docs/v7/features/continuous-testing.mdx +346 -0
- package/docs/v7/features/coverage.mdx +508 -0
- package/docs/v7/features/data-driven-testing.mdx +441 -0
- package/docs/v7/features/easy-to-write.mdx +2 -73
- package/docs/v7/features/enterprise.mdx +155 -39
- package/docs/v7/features/fast.mdx +63 -81
- package/docs/v7/features/managed-sandboxes.mdx +384 -0
- package/docs/v7/features/network-monitoring.mdx +568 -0
- package/docs/v7/features/observable.mdx +3 -22
- package/docs/v7/features/parallel-execution.mdx +381 -0
- package/docs/v7/features/powerful.mdx +1 -1
- package/docs/v7/features/reports.mdx +414 -0
- package/docs/v7/features/sandbox-customization.mdx +229 -0
- package/docs/v7/features/scalable.mdx +217 -2
- package/docs/v7/features/stable.mdx +106 -147
- package/docs/v7/features/system-performance.mdx +616 -0
- package/docs/v7/features/test-analytics.mdx +373 -0
- package/docs/v7/features/test-cases.mdx +393 -0
- package/docs/v7/features/test-replays.mdx +408 -0
- package/docs/v7/features/test-reports.mdx +308 -0
- package/docs/v7/getting-started/{running-and-debugging.mdx → debugging-tests.mdx} +12 -142
- package/docs/v7/getting-started/quickstart.mdx +22 -305
- package/docs/v7/getting-started/running-tests.mdx +173 -0
- package/docs/v7/overview/what-is-testdriver.mdx +2 -14
- package/docs/v7/presets/chrome-extension.mdx +147 -122
- package/interfaces/cli/commands/init.js +3 -3
- package/interfaces/cli/lib/base.js +3 -2
- package/interfaces/logger.js +0 -2
- package/interfaces/shared-test-state.mjs +0 -5
- package/interfaces/vitest-plugin.mjs +70 -50
- package/lib/core/Dashcam.js +60 -85
- package/lib/vitest/hooks.mjs +42 -50
- package/package.json +1 -1
- package/sdk-log-formatter.js +350 -175
- package/sdk.d.ts +36 -3
- package/sdk.js +431 -116
- package/setup/aws/cloudformation.yaml +2 -2
- package/setup/aws/self-hosted.yml +1 -1
- package/test/testdriver/chrome-extension.test.mjs +55 -72
- package/test/testdriver/element-not-found.test.mjs +2 -1
- package/test/testdriver/hover-image.test.mjs +1 -1
- package/test/testdriver/scroll-until-text.test.mjs +10 -6
- package/test/testdriver/setup/lifecycleHelpers.mjs +19 -24
- package/test/testdriver/setup/testHelpers.mjs +18 -23
- package/vitest.config.mjs +3 -3
- package/.github/workflows/linux-tests.yml +0 -28
- package/docs/v7/getting-started/generating-tests.mdx +0 -525
- package/test/testdriver/auto-cache-key-demo.test.mjs +0 -56
|
@@ -168,14 +168,14 @@ Resources:
|
|
|
168
168
|
IpProtocol: tcp,
|
|
169
169
|
FromPort: 8765,
|
|
170
170
|
ToPort: 8765,
|
|
171
|
-
CidrIp:
|
|
171
|
+
CidrIp: 74.220.58.0/24,
|
|
172
172
|
Description: "pyautogui-cli WebSockets - Static IP 1",
|
|
173
173
|
}
|
|
174
174
|
- {
|
|
175
175
|
IpProtocol: tcp,
|
|
176
176
|
FromPort: 8765,
|
|
177
177
|
ToPort: 8765,
|
|
178
|
-
CidrIp:
|
|
178
|
+
CidrIp: 74.220.50.0/24,
|
|
179
179
|
Description: "pyautogui-cli WebSockets - Static IP 2",
|
|
180
180
|
}
|
|
181
181
|
- {
|
|
@@ -78,7 +78,7 @@ jobs:
|
|
|
78
78
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
79
79
|
AWS_REGION: us-east-2
|
|
80
80
|
AWS_LAUNCH_TEMPLATE_ID: lt-00d02f31cfc602f27
|
|
81
|
-
AMI_ID: ami-
|
|
81
|
+
AMI_ID: ami-0c2858680200ac890
|
|
82
82
|
RESOLUTION: 1920x1080
|
|
83
83
|
- name: Run TestDriver
|
|
84
84
|
run: node bin/testdriverai.js run testdriver/acceptance/${{ matrix.test }} --ip="${{ steps.aws-setup.outputs.public-ip }}" --junit=out.xml
|
|
@@ -1,89 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Chrome Extension
|
|
3
|
-
*
|
|
2
|
+
* TestDriver SDK - Chrome Extension Test (Vitest)
|
|
3
|
+
* Tests loading a Chrome extension using provision.chromeExtension()
|
|
4
4
|
*
|
|
5
|
-
* This test
|
|
6
|
-
*
|
|
5
|
+
* This test suite covers:
|
|
6
|
+
* 1. Loading extension from local path (extensionPath)
|
|
7
|
+
* 2. Loading extension from Chrome Web Store (extensionId)
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
|
-
import {
|
|
10
|
-
import TestDriver from "../../
|
|
11
|
-
import {
|
|
12
|
-
runPostrun,
|
|
13
|
-
runPrerunChromeExtension
|
|
14
|
-
} from "./setup/lifecycleHelpers.mjs";
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
15
12
|
|
|
16
|
-
describe("Chrome Extension
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
describe("Chrome Extension Test", () => {
|
|
14
|
+
it("should load hello-world Chrome extension from local path", async (context) => {
|
|
15
|
+
const testdriver = TestDriver(context, { headless: false, newSandbox: true });
|
|
16
|
+
|
|
17
|
+
// Wait for connection to be ready before running exec
|
|
18
|
+
await testdriver.ready();
|
|
19
|
+
|
|
20
|
+
// Clone the Chrome extensions samples repo
|
|
21
|
+
await testdriver.exec(
|
|
22
|
+
'sh',
|
|
23
|
+
'git clone --depth 1 https://github.com/GoogleChrome/chrome-extensions-samples.git /tmp/chrome-extensions-samples',
|
|
24
|
+
60000,
|
|
25
|
+
true
|
|
26
|
+
);
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
apiRoot: process.env.TD_API_ROOT,
|
|
25
|
-
os: "linux",
|
|
26
|
-
verbosity: 1,
|
|
28
|
+
// Launch Chrome with the hello-world extension loaded
|
|
29
|
+
await testdriver.provision.chromeExtension({
|
|
30
|
+
extensionPath: '/tmp/chrome-extensions-samples/functional-samples/tutorial.hello-world',
|
|
31
|
+
url: 'https://testdriver.ai'
|
|
27
32
|
});
|
|
28
33
|
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (client) {
|
|
36
|
-
dashcamUrl = await runPostrun(client);
|
|
37
|
-
await client.cleanup();
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("should load Chrome with extension and verify functionality", async () => {
|
|
42
|
-
// Focus Chrome browser
|
|
43
|
-
await client.focusApplication("Google Chrome");
|
|
44
|
-
|
|
45
|
-
// Verify the page loaded
|
|
46
|
-
const pageElement = await client.find("TestDriver.ai Sandbox");
|
|
47
|
-
expect(pageElement.found()).toBe(true);
|
|
34
|
+
// The hello-world extension adds a puzzle piece icon to the toolbar
|
|
35
|
+
// When clicked, it shows a popup with "Hello Extensions"
|
|
36
|
+
|
|
37
|
+
// First, let's verify Chrome loaded and we can see the page
|
|
38
|
+
const pageResult = await testdriver.assert("the testdriver.ai website is visible");
|
|
39
|
+
expect(pageResult).toBeTruthy();
|
|
48
40
|
|
|
49
|
-
//
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
);
|
|
53
|
-
await signInButton.click();
|
|
41
|
+
// Click on the extensions button (puzzle piece icon) in Chrome toolbar
|
|
42
|
+
const extensionsButton = await testdriver.find("The puzzle-shaped icon in the Chrome toolbar.");
|
|
43
|
+
await extensionsButton.click();
|
|
54
44
|
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
expect(result).toBeTruthy();
|
|
45
|
+
// Look for the hello world extension in the extensions menu
|
|
46
|
+
const helloExtension = await testdriver.find("Hello Extensions extension in the extensions dropdown");
|
|
47
|
+
await helloExtension.click();
|
|
60
48
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
49
|
+
// Verify the extension popup shows "Hello Extensions" text
|
|
50
|
+
const popupResult = await testdriver.assert("a popup shows with the text 'Hello Extensions'");
|
|
51
|
+
expect(popupResult).toBeTruthy();
|
|
65
52
|
});
|
|
66
53
|
|
|
67
|
-
it("should
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Example: Navigate to extension management page to verify it's loaded
|
|
77
|
-
await client.exec(
|
|
78
|
-
"sh",
|
|
79
|
-
`xdotool key --clearmodifiers ctrl+shift+e`,
|
|
80
|
-
5000,
|
|
81
|
-
true
|
|
82
|
-
);
|
|
54
|
+
it("should load Loom from Chrome Web Store by extensionId", async (context) => {
|
|
55
|
+
const testdriver = TestDriver(context, { headless: false, newSandbox: true});
|
|
56
|
+
|
|
57
|
+
// Launch Chrome with Loom loaded by its Chrome Web Store ID
|
|
58
|
+
// Loom ID: liecbddmkiiihnedobmlmillhodjkdmb
|
|
59
|
+
await testdriver.provision.chromeExtension({
|
|
60
|
+
extensionId: 'liecbddmkiiihnedobmlmillhodjkdmb',
|
|
61
|
+
url: 'https://testdriver.ai'
|
|
62
|
+
});
|
|
83
63
|
|
|
84
|
-
//
|
|
85
|
-
|
|
64
|
+
// Click on the extensions button (puzzle piece icon) in Chrome toolbar
|
|
65
|
+
const extensionsButton = await testdriver.find("The puzzle-shaped icon in the Chrome toolbar.");
|
|
66
|
+
await extensionsButton.click();
|
|
86
67
|
|
|
87
|
-
|
|
68
|
+
// Look for Loom in the extensions menu
|
|
69
|
+
const loomExtension = await testdriver.find("Loom extension in the extensions dropdown");
|
|
70
|
+
expect(loomExtension.found()).toBeTruthy();
|
|
88
71
|
});
|
|
89
72
|
});
|
|
@@ -21,5 +21,6 @@ describe("Element Not Found Test", () => {
|
|
|
21
21
|
// Should return an element that is not found
|
|
22
22
|
expect(element.found()).toBe(false);
|
|
23
23
|
expect(element.coordinates).toBeNull();
|
|
24
|
-
}
|
|
24
|
+
}); // 90 second timeout for the test (should complete much faster)
|
|
25
25
|
});
|
|
26
|
+
|
|
@@ -9,7 +9,7 @@ import { performLogin } from "./setup/testHelpers.mjs";
|
|
|
9
9
|
|
|
10
10
|
describe("Hover Image Test", () => {
|
|
11
11
|
it("should click on shopping cart icon and verify empty cart", async (context) => {
|
|
12
|
-
const testdriver = TestDriver(context, { headless:
|
|
12
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
13
13
|
|
|
14
14
|
// provision.chrome() automatically calls ready() and starts dashcam
|
|
15
15
|
await testdriver.provision.chrome({
|
|
@@ -9,7 +9,7 @@ import { performLogin } from "./setup/testHelpers.mjs";
|
|
|
9
9
|
|
|
10
10
|
describe("Scroll Until Text Test", () => {
|
|
11
11
|
it('should scroll until "testdriver socks" appears', async (context) => {
|
|
12
|
-
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
+
const testdriver = TestDriver(context, { headless: true, reconnect: false });
|
|
13
13
|
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
14
14
|
|
|
15
15
|
//
|
|
@@ -18,18 +18,22 @@ describe("Scroll Until Text Test", () => {
|
|
|
18
18
|
|
|
19
19
|
// Scroll until text appears
|
|
20
20
|
await testdriver.focusApplication("Google Chrome");
|
|
21
|
+
|
|
22
|
+
await testdriver.find('TestDriver.ai Sandbox heading').click();
|
|
23
|
+
|
|
21
24
|
// Scroll until text appears
|
|
22
25
|
let found = false;
|
|
23
26
|
let scrollCount = 0;
|
|
24
27
|
const maxScrolls = 10;
|
|
25
28
|
|
|
26
29
|
while (!found && scrollCount < maxScrolls) {
|
|
27
|
-
const findResult = await testdriver.find("testdriver socks");
|
|
28
|
-
|
|
29
|
-
found
|
|
30
|
+
const findResult = await testdriver.find("testdriver socks product text is fully visible");
|
|
31
|
+
|
|
32
|
+
if (findResult.found()) {
|
|
33
|
+
found = true;
|
|
30
34
|
} else {
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
await testdriver.scroll();
|
|
36
|
+
scrollCount++;
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -86,13 +86,6 @@ export async function stopDashcam(client) {
|
|
|
86
86
|
const dashcam = getDashcam(client);
|
|
87
87
|
const url = await dashcam.stop();
|
|
88
88
|
|
|
89
|
-
if (url) {
|
|
90
|
-
console.log("✅ Found dashcam URL:", url);
|
|
91
|
-
console.log("🎥 Dashcam URL:", url);
|
|
92
|
-
} else {
|
|
93
|
-
console.warn("⚠️ No replay URL found in dashcam output");
|
|
94
|
-
}
|
|
95
|
-
|
|
96
89
|
return url;
|
|
97
90
|
}
|
|
98
91
|
|
|
@@ -116,7 +109,7 @@ export async function launchChrome(
|
|
|
116
109
|
} else {
|
|
117
110
|
await client.exec(
|
|
118
111
|
shell,
|
|
119
|
-
`google-chrome --start-maximized --disable-fre --no-default-browser-check --no-first-run --guest "${url}" >/dev/null 2>&1 &`,
|
|
112
|
+
`google-chrome --start-maximized --disable-fre --no-default-browser-check --no-first-run --no-experiments --guest "${url}" >/dev/null 2>&1 &`,
|
|
120
113
|
30000,
|
|
121
114
|
);
|
|
122
115
|
}
|
|
@@ -188,13 +181,13 @@ export async function launchChromeForTesting(
|
|
|
188
181
|
// For now, fallback to regular Chrome on Windows
|
|
189
182
|
await client.exec(
|
|
190
183
|
"pwsh",
|
|
191
|
-
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--user-data-dir=${userDataDir}", "--disable-fre", "--no-default-browser-check", "--no-first-run", "${url}"`,
|
|
184
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--user-data-dir=${userDataDir}", "--disable-fre", "--no-default-browser-check", "--no-first-run", "--no-experiments", "${url}"`,
|
|
192
185
|
30000,
|
|
193
186
|
);
|
|
194
187
|
} else {
|
|
195
188
|
await client.exec(
|
|
196
189
|
shell,
|
|
197
|
-
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --user-data-dir=${userDataDir} "${url}" >/dev/null 2>&1 &`,
|
|
190
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --no-experiments --user-data-dir=${userDataDir} "${url}" >/dev/null 2>&1 &`,
|
|
198
191
|
30000,
|
|
199
192
|
);
|
|
200
193
|
}
|
|
@@ -202,19 +195,18 @@ export async function launchChromeForTesting(
|
|
|
202
195
|
|
|
203
196
|
/**
|
|
204
197
|
* Launch Chrome for Testing with a Chrome extension loaded
|
|
198
|
+
* Also loads dashcam-chrome extension for web log capture on Linux
|
|
205
199
|
* @param {TestDriver} client - TestDriver client
|
|
206
|
-
* @param {string}
|
|
200
|
+
* @param {string} extensionPath - Local filesystem path to the unpacked extension directory
|
|
207
201
|
* @param {string} url - URL to open (default: https://testdriver-sandbox.vercel.app/)
|
|
208
202
|
* @example
|
|
209
|
-
* //
|
|
210
|
-
* await
|
|
211
|
-
*
|
|
212
|
-
* // Launch with multiple extensions (comma-separated)
|
|
213
|
-
* await launchChromeExtension(client, "cjpalhdlnbpafiamejdnhcphjbkeiagm,nngceckbapebfimnlniiiahkandclblb");
|
|
203
|
+
* // Clone an extension and launch Chrome with it
|
|
204
|
+
* await client.exec('sh', 'git clone https://github.com/user/extension.git /tmp/extension');
|
|
205
|
+
* await launchChromeExtension(client, '/tmp/extension');
|
|
214
206
|
*/
|
|
215
207
|
export async function launchChromeExtension(
|
|
216
208
|
client,
|
|
217
|
-
|
|
209
|
+
extensionPath,
|
|
218
210
|
url = "http://testdriver-sandbox.vercel.app/",
|
|
219
211
|
) {
|
|
220
212
|
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
@@ -274,13 +266,15 @@ export async function launchChromeExtension(
|
|
|
274
266
|
// For now, fallback to regular Chrome on Windows
|
|
275
267
|
await client.exec(
|
|
276
268
|
"pwsh",
|
|
277
|
-
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--user-data-dir=${userDataDir}", "--load-extension=${
|
|
269
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--user-data-dir=${userDataDir}", "--load-extension=${extensionPath}", "${url}"`,
|
|
278
270
|
30000,
|
|
279
271
|
);
|
|
280
272
|
} else {
|
|
273
|
+
// Load both user extension and dashcam-chrome for web log capture
|
|
274
|
+
const extensionsToLoad = `${extensionPath},/usr/lib/node_modules/dashcam-chrome/build`;
|
|
281
275
|
await client.exec(
|
|
282
276
|
shell,
|
|
283
|
-
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --user-data-dir=${userDataDir} --load-extension=${
|
|
277
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --no-experiments --user-data-dir=${userDataDir} --load-extension=${extensionsToLoad} "${url}" >/dev/null 2>&1 &`,
|
|
284
278
|
30000,
|
|
285
279
|
);
|
|
286
280
|
}
|
|
@@ -338,16 +332,17 @@ export async function runPrerunChromeForTesting(client) {
|
|
|
338
332
|
* Run prerun lifecycle hooks with Chrome extension loaded
|
|
339
333
|
* Implements lifecycle/prerun.yaml functionality with a Chrome extension
|
|
340
334
|
* @param {TestDriver} client - TestDriver client
|
|
341
|
-
* @param {string}
|
|
335
|
+
* @param {string} extensionPath - Local filesystem path to the unpacked extension directory
|
|
342
336
|
* @example
|
|
343
|
-
* //
|
|
344
|
-
* await
|
|
337
|
+
* // Clone an extension and run prerun with it
|
|
338
|
+
* await client.exec('sh', 'git clone https://github.com/user/extension.git /tmp/extension');
|
|
339
|
+
* await runPrerunChromeExtension(client, '/tmp/extension');
|
|
345
340
|
*/
|
|
346
|
-
export async function runPrerunChromeExtension(client,
|
|
341
|
+
export async function runPrerunChromeExtension(client, extensionPath) {
|
|
347
342
|
await authDashcam(client);
|
|
348
343
|
await addDashcamLog(client);
|
|
349
344
|
await startDashcam(client);
|
|
350
|
-
await launchChromeExtension(client,
|
|
345
|
+
await launchChromeExtension(client, extensionPath);
|
|
351
346
|
await waitForPage(client, "TestDriver.ai Sandbox");
|
|
352
347
|
}
|
|
353
348
|
|
|
@@ -11,26 +11,26 @@ import path, { dirname } from "path";
|
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
12
|
import TestDriver from "../../../sdk.js";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
addDashcamLog,
|
|
15
|
+
authDashcam,
|
|
16
|
+
launchChrome,
|
|
17
|
+
runPostrun,
|
|
18
|
+
runPrerun,
|
|
19
|
+
startDashcam,
|
|
20
|
+
stopDashcam,
|
|
21
|
+
waitForPage,
|
|
22
22
|
} from "./lifecycleHelpers.mjs";
|
|
23
23
|
|
|
24
24
|
// Re-export lifecycle helpers for backward compatibility
|
|
25
25
|
export {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
addDashcamLog,
|
|
27
|
+
authDashcam,
|
|
28
|
+
launchChrome,
|
|
29
|
+
runPostrun,
|
|
30
|
+
runPrerun,
|
|
31
|
+
startDashcam,
|
|
32
|
+
stopDashcam,
|
|
33
|
+
waitForPage
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
// Get the directory of the current module
|
|
@@ -70,8 +70,6 @@ export function storeTestResult(
|
|
|
70
70
|
dashcamUrl,
|
|
71
71
|
sessionInfo = {},
|
|
72
72
|
) {
|
|
73
|
-
console.log(`📝 Storing test result: ${testName}`);
|
|
74
|
-
console.log(` Dashcam URL: ${dashcamUrl || "none"}`);
|
|
75
73
|
|
|
76
74
|
// Extract replay object ID from dashcam URL
|
|
77
75
|
let replayObjectId = null;
|
|
@@ -548,9 +546,7 @@ export async function teardownTest(client, options = {}) {
|
|
|
548
546
|
};
|
|
549
547
|
|
|
550
548
|
fs.writeFileSync(testResultFile, JSON.stringify(testResult, null, 2));
|
|
551
|
-
|
|
552
|
-
`[TestHelpers] ✅ Wrote test result to file: ${testResultFile} (testFile: ${testFile}, testOrder: ${testOrder})`,
|
|
553
|
-
);
|
|
549
|
+
|
|
554
550
|
} catch (error) {
|
|
555
551
|
console.error(
|
|
556
552
|
`[TestHelpers] ❌ Failed to write test result file:`,
|
|
@@ -570,7 +566,6 @@ export async function teardownTest(client, options = {}) {
|
|
|
570
566
|
console.log("🔌 Disconnecting client...");
|
|
571
567
|
try {
|
|
572
568
|
await client.disconnect();
|
|
573
|
-
console.log("✅ Client disconnected");
|
|
574
569
|
} catch (disconnectError) {
|
|
575
570
|
console.error("❌ Error disconnecting:", disconnectError.message);
|
|
576
571
|
// Don't throw - we're already in cleanup
|
|
@@ -614,7 +609,7 @@ export async function performLogin(
|
|
|
614
609
|
|
|
615
610
|
// Get password from screen if not provided
|
|
616
611
|
if (!password) {
|
|
617
|
-
password = await client.
|
|
612
|
+
password = await client.extract("the password");
|
|
618
613
|
}
|
|
619
614
|
|
|
620
615
|
const usernameField = await client.find(
|
package/vitest.config.mjs
CHANGED
|
@@ -8,12 +8,12 @@ config();
|
|
|
8
8
|
|
|
9
9
|
export default defineConfig({
|
|
10
10
|
test: {
|
|
11
|
-
testTimeout:
|
|
12
|
-
hookTimeout:
|
|
11
|
+
testTimeout: 900000,
|
|
12
|
+
hookTimeout: 900000,
|
|
13
13
|
reporters: [
|
|
14
14
|
'default',
|
|
15
|
-
// Don't pass apiKey/apiRoot here - they'll be read from env at runtime
|
|
16
15
|
TestDriver(),
|
|
16
|
+
['junit', { outputFile: 'test-report.junit.xml' }]
|
|
17
17
|
],
|
|
18
18
|
setupFiles: ['testdriverai/vitest/setup'],
|
|
19
19
|
},
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: Linux Tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ main, develop ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main, develop ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- name: Setup Node.js
|
|
17
|
-
uses: actions/setup-node@v4
|
|
18
|
-
with:
|
|
19
|
-
node-version: '20'
|
|
20
|
-
cache: 'npm'
|
|
21
|
-
|
|
22
|
-
- name: Install dependencies
|
|
23
|
-
run: npm ci
|
|
24
|
-
|
|
25
|
-
- name: Run Linux tests
|
|
26
|
-
run: npx vitest run test/testdriver/assert.test.mjs
|
|
27
|
-
env:
|
|
28
|
-
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|