testdriverai 7.1.2 → 7.1.4
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/test-init.yml +145 -0
- package/agent/lib/commander.js +2 -2
- package/agent/lib/commands.js +10 -5
- package/docs/docs.json +29 -84
- package/docs/v7/_drafts/migration.mdx +3 -3
- package/docs/v7/api/act.mdx +1 -1
- package/docs/v7/api/assert.mdx +1 -1
- package/docs/v7/api/assertions.mdx +14 -14
- package/docs/v7/getting-started/quickstart.mdx +11 -9
- package/docs/v7/getting-started/running-and-debugging.mdx +3 -2
- package/docs/v7/getting-started/writing-tests.mdx +4 -5
- package/docs/v7/overview/readme.mdx +1 -1
- package/docs/v7/presets/chrome.mdx +38 -41
- package/docs/v7/presets/electron.mdx +107 -100
- package/docs/v7/presets/webapp.mdx +40 -43
- package/interfaces/cli/commands/init.js +79 -21
- package/interfaces/vitest-plugin.mjs +36 -9
- package/lib/vitest/hooks.mjs +5 -1
- package/manual/test-init-command.js +223 -0
- package/package.json +2 -2
- package/schema.json +5 -5
- package/sdk-log-formatter.js +1 -1
- package/sdk.d.ts +8 -8
- package/sdk.js +64 -14
- package/test/testdriver/exec-output.test.mjs +1 -1
- package/test/testdriver/exec-pwsh.test.mjs +1 -1
- package/test/testdriver/focus-window.test.mjs +1 -1
- package/test/testdriver/hover-image.test.mjs +1 -1
- package/test/testdriver/hover-text-with-description.test.mjs +0 -3
- package/test/testdriver/match-image.test.mjs +1 -1
- package/test/testdriver/scroll-keyboard.test.mjs +1 -1
- package/test/testdriver/scroll-until-image.test.mjs +1 -1
- package/test/testdriver/scroll-until-text.test.mjs +18 -1
- package/test/testdriver/scroll.test.mjs +1 -1
- package/test/testdriver/setup/lifecycleHelpers.mjs +105 -5
- package/test/testdriver/setup/testHelpers.mjs +6 -2
- package/vitest.config.mjs +7 -2
- package/test/testdriver/exec-js.test.mjs +0 -43
|
@@ -123,7 +123,7 @@ export async function launchChrome(
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
|
-
* Launch Chrome for Testing browser with
|
|
126
|
+
* Launch Chrome for Testing browser with custom profile
|
|
127
127
|
* @param {TestDriver} client - TestDriver client
|
|
128
128
|
* @param {string} url - URL to open (default: https://testdriver-sandbox.vercel.app/)
|
|
129
129
|
*/
|
|
@@ -132,19 +132,69 @@ export async function launchChromeForTesting(
|
|
|
132
132
|
url = "http://testdriver-sandbox.vercel.app/",
|
|
133
133
|
) {
|
|
134
134
|
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
135
|
+
const userDataDir = client.os === "windows"
|
|
136
|
+
? "C:\\Users\\testdriver\\AppData\\Local\\TestDriver\\Chrome"
|
|
137
|
+
: "/tmp/testdriver-chrome-profile";
|
|
138
|
+
|
|
139
|
+
// Create user data directory and Default profile directory
|
|
140
|
+
const defaultProfileDir = client.os === "windows"
|
|
141
|
+
? `${userDataDir}\\Default`
|
|
142
|
+
: `${userDataDir}/Default`;
|
|
143
|
+
|
|
144
|
+
const createDirCmd = client.os === "windows"
|
|
145
|
+
? `New-Item -ItemType Directory -Path "${defaultProfileDir}" -Force | Out-Null`
|
|
146
|
+
: `mkdir -p "${defaultProfileDir}"`;
|
|
147
|
+
|
|
148
|
+
await client.exec(shell, createDirCmd, 10000, true);
|
|
149
|
+
|
|
150
|
+
// Write Chrome preferences
|
|
151
|
+
const chromePrefs = {
|
|
152
|
+
credentials_enable_service: false,
|
|
153
|
+
profile: {
|
|
154
|
+
password_manager_enabled: false,
|
|
155
|
+
default_content_setting_values: {}
|
|
156
|
+
},
|
|
157
|
+
signin: {
|
|
158
|
+
allowed: false
|
|
159
|
+
},
|
|
160
|
+
sync: {
|
|
161
|
+
requested: false,
|
|
162
|
+
first_setup_complete: true,
|
|
163
|
+
sync_all_os_types: false
|
|
164
|
+
},
|
|
165
|
+
autofill: {
|
|
166
|
+
enabled: false
|
|
167
|
+
},
|
|
168
|
+
local_state: {
|
|
169
|
+
browser: {
|
|
170
|
+
has_seen_welcome_page: true
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const prefsPath = client.os === "windows"
|
|
176
|
+
? `${defaultProfileDir}\\Preferences`
|
|
177
|
+
: `${defaultProfileDir}/Preferences`;
|
|
178
|
+
|
|
179
|
+
const prefsJson = JSON.stringify(chromePrefs, null, 2);
|
|
180
|
+
const writePrefCmd = client.os === "windows"
|
|
181
|
+
? `Set-Content -Path "${prefsPath}" -Value '${prefsJson.replace(/'/g, "''")}'`
|
|
182
|
+
: `cat > "${prefsPath}" << 'EOF'\n${prefsJson}\nEOF`;
|
|
183
|
+
|
|
184
|
+
await client.exec(shell, writePrefCmd, 10000, true);
|
|
135
185
|
|
|
136
186
|
if (client.os === "windows") {
|
|
137
187
|
// Windows Chrome for Testing path would need to be determined
|
|
138
188
|
// For now, fallback to regular Chrome on Windows
|
|
139
189
|
await client.exec(
|
|
140
190
|
"pwsh",
|
|
141
|
-
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--
|
|
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}"`,
|
|
142
192
|
30000,
|
|
143
193
|
);
|
|
144
194
|
} else {
|
|
145
195
|
await client.exec(
|
|
146
196
|
shell,
|
|
147
|
-
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --
|
|
197
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --user-data-dir=${userDataDir} "${url}" >/dev/null 2>&1 &`,
|
|
148
198
|
30000,
|
|
149
199
|
);
|
|
150
200
|
}
|
|
@@ -168,19 +218,69 @@ export async function launchChromeExtension(
|
|
|
168
218
|
url = "http://testdriver-sandbox.vercel.app/",
|
|
169
219
|
) {
|
|
170
220
|
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
221
|
+
const userDataDir = client.os === "windows"
|
|
222
|
+
? "C:\\Users\\testdriver\\AppData\\Local\\TestDriver\\Chrome"
|
|
223
|
+
: "/tmp/testdriver-chrome-profile";
|
|
224
|
+
|
|
225
|
+
// Create user data directory and Default profile directory
|
|
226
|
+
const defaultProfileDir = client.os === "windows"
|
|
227
|
+
? `${userDataDir}\\Default`
|
|
228
|
+
: `${userDataDir}/Default`;
|
|
229
|
+
|
|
230
|
+
const createDirCmd = client.os === "windows"
|
|
231
|
+
? `New-Item -ItemType Directory -Path "${defaultProfileDir}" -Force | Out-Null`
|
|
232
|
+
: `mkdir -p "${defaultProfileDir}"`;
|
|
233
|
+
|
|
234
|
+
await client.exec(shell, createDirCmd, 10000, true);
|
|
235
|
+
|
|
236
|
+
// Write Chrome preferences
|
|
237
|
+
const chromePrefs = {
|
|
238
|
+
credentials_enable_service: false,
|
|
239
|
+
profile: {
|
|
240
|
+
password_manager_enabled: false,
|
|
241
|
+
default_content_setting_values: {}
|
|
242
|
+
},
|
|
243
|
+
signin: {
|
|
244
|
+
allowed: false
|
|
245
|
+
},
|
|
246
|
+
sync: {
|
|
247
|
+
requested: false,
|
|
248
|
+
first_setup_complete: true,
|
|
249
|
+
sync_all_os_types: false
|
|
250
|
+
},
|
|
251
|
+
autofill: {
|
|
252
|
+
enabled: false
|
|
253
|
+
},
|
|
254
|
+
local_state: {
|
|
255
|
+
browser: {
|
|
256
|
+
has_seen_welcome_page: true
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const prefsPath = client.os === "windows"
|
|
262
|
+
? `${defaultProfileDir}\\Preferences`
|
|
263
|
+
: `${defaultProfileDir}/Preferences`;
|
|
264
|
+
|
|
265
|
+
const prefsJson = JSON.stringify(chromePrefs, null, 2);
|
|
266
|
+
const writePrefCmd = client.os === "windows"
|
|
267
|
+
? `Set-Content -Path "${prefsPath}" -Value '${prefsJson.replace(/'/g, "''")}'`
|
|
268
|
+
: `cat > "${prefsPath}" << 'EOF'\n${prefsJson}\nEOF`;
|
|
269
|
+
|
|
270
|
+
await client.exec(shell, writePrefCmd, 10000, true);
|
|
171
271
|
|
|
172
272
|
if (client.os === "windows") {
|
|
173
273
|
// Windows Chrome for Testing path would need to be determined
|
|
174
274
|
// For now, fallback to regular Chrome on Windows
|
|
175
275
|
await client.exec(
|
|
176
276
|
"pwsh",
|
|
177
|
-
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--load-extension=${extensionId}", "${url}"`,
|
|
277
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--user-data-dir=${userDataDir}", "--load-extension=${extensionId}", "${url}"`,
|
|
178
278
|
30000,
|
|
179
279
|
);
|
|
180
280
|
} else {
|
|
181
281
|
await client.exec(
|
|
182
282
|
shell,
|
|
183
|
-
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --load-extension=${extensionId} "${url}" >/dev/null 2>&1 &`,
|
|
283
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --user-data-dir=${userDataDir} --load-extension=${extensionId} "${url}" >/dev/null 2>&1 &`,
|
|
184
284
|
30000,
|
|
185
285
|
);
|
|
186
286
|
}
|
|
@@ -511,9 +511,13 @@ export async function teardownTest(client, options = {}) {
|
|
|
511
511
|
fs.mkdirSync(dir, { recursive: true });
|
|
512
512
|
}
|
|
513
513
|
|
|
514
|
-
// Get test file path
|
|
515
|
-
const
|
|
514
|
+
// Get test file path - make it relative to project root
|
|
515
|
+
const absolutePath =
|
|
516
516
|
options.task.file?.filepath || options.task.file?.name || "unknown";
|
|
517
|
+
const projectRoot = process.cwd();
|
|
518
|
+
const testFile = absolutePath !== "unknown"
|
|
519
|
+
? path.relative(projectRoot, absolutePath)
|
|
520
|
+
: absolutePath;
|
|
517
521
|
|
|
518
522
|
// Calculate test order (index within parent suite)
|
|
519
523
|
let testOrder = 0;
|
package/vitest.config.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
1
2
|
import TestDriver from 'testdriverai/vitest';
|
|
2
3
|
import { defineConfig } from 'vitest/config';
|
|
3
4
|
|
|
5
|
+
// Load .env file early so it's available to the reporter (runs in main process)
|
|
6
|
+
// and to worker processes
|
|
7
|
+
config();
|
|
8
|
+
|
|
4
9
|
export default defineConfig({
|
|
5
10
|
test: {
|
|
6
|
-
testTimeout:
|
|
7
|
-
hookTimeout:
|
|
11
|
+
testTimeout: 300000,
|
|
12
|
+
hookTimeout: 300000,
|
|
8
13
|
reporters: [
|
|
9
14
|
'default',
|
|
10
15
|
// Don't pass apiKey/apiRoot here - they'll be read from env at runtime
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TestDriver SDK - Exec JS Test (Vitest)
|
|
3
|
-
* Converted from: testdriver/acceptance/exec-js.yaml
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, expect, it } from "vitest";
|
|
7
|
-
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
|
-
|
|
9
|
-
describe("Exec JavaScript Test", () => {
|
|
10
|
-
it("should fetch user data from API and enter email", async (context) => {
|
|
11
|
-
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
-
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
// Execute JavaScript to fetch user data
|
|
16
|
-
const userEmail = await testdriver.exec(
|
|
17
|
-
"js",
|
|
18
|
-
`
|
|
19
|
-
const response = await fetch('https://jsonplaceholder.typicode.com/users');
|
|
20
|
-
const user = await response.json();
|
|
21
|
-
console.log('user', user[0]);
|
|
22
|
-
result = user[0].email;
|
|
23
|
-
`,
|
|
24
|
-
10000,
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
expect(userEmail).toBeTruthy();
|
|
28
|
-
expect(userEmail).toContain("@");
|
|
29
|
-
|
|
30
|
-
// Enter email in username field
|
|
31
|
-
const usernameField = await testdriver.find(
|
|
32
|
-
"Username, input field for username",
|
|
33
|
-
);
|
|
34
|
-
await usernameField.click();
|
|
35
|
-
await testdriver.type(userEmail);
|
|
36
|
-
|
|
37
|
-
// Assert email is in the field
|
|
38
|
-
const result = await testdriver.assert(
|
|
39
|
-
'the username field contains "Sincere@april.biz" which is a valid email address',
|
|
40
|
-
);
|
|
41
|
-
expect(result).toBeTruthy();
|
|
42
|
-
});
|
|
43
|
-
});
|