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
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test Init Command
|
|
5
|
+
*
|
|
6
|
+
* This script tests the `testdriverai init` command by:
|
|
7
|
+
* 1. Creating a temporary test project
|
|
8
|
+
* 2. Running the init command
|
|
9
|
+
* 3. Verifying all files were created correctly
|
|
10
|
+
* 4. Running the generated test
|
|
11
|
+
* 5. Cleaning up
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node manual/test-init-command.js
|
|
15
|
+
*
|
|
16
|
+
* Requirements:
|
|
17
|
+
* - TD_API_KEY environment variable must be set
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const { execSync } = require('child_process');
|
|
23
|
+
const os = require('os');
|
|
24
|
+
|
|
25
|
+
// Colors for terminal output
|
|
26
|
+
const colors = {
|
|
27
|
+
reset: '\x1b[0m',
|
|
28
|
+
green: '\x1b[32m',
|
|
29
|
+
red: '\x1b[31m',
|
|
30
|
+
cyan: '\x1b[36m',
|
|
31
|
+
yellow: '\x1b[33m',
|
|
32
|
+
gray: '\x1b[90m',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function log(message, color = 'reset') {
|
|
36
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function success(message) {
|
|
40
|
+
log(`✓ ${message}`, 'green');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function error(message) {
|
|
44
|
+
log(`✗ ${message}`, 'red');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function info(message) {
|
|
48
|
+
log(message, 'cyan');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function step(message) {
|
|
52
|
+
log(`\n${message}`, 'cyan');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Main test function
|
|
56
|
+
async function testInitCommand() {
|
|
57
|
+
// Check for API key
|
|
58
|
+
if (!process.env.TD_API_KEY) {
|
|
59
|
+
error('TD_API_KEY environment variable is required');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const testDir = path.join(os.tmpdir(), `test-init-${Date.now()}`);
|
|
64
|
+
const cliPath = path.join(__dirname, '..');
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
step('📦 Creating test directory...');
|
|
68
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
69
|
+
success(`Created: ${testDir}`);
|
|
70
|
+
|
|
71
|
+
step('🔧 Setting up .env file...');
|
|
72
|
+
const envContent = `TD_API_KEY=${process.env.TD_API_KEY}\n`;
|
|
73
|
+
fs.writeFileSync(path.join(testDir, '.env'), envContent);
|
|
74
|
+
success('Created .env with API key');
|
|
75
|
+
|
|
76
|
+
step('🚀 Running init command...');
|
|
77
|
+
try {
|
|
78
|
+
execSync(`node ${path.join(cliPath, 'bin/testdriverai.js')} init`, {
|
|
79
|
+
cwd: testDir,
|
|
80
|
+
stdio: 'inherit',
|
|
81
|
+
env: { ...process.env, TD_API_KEY: process.env.TD_API_KEY }
|
|
82
|
+
});
|
|
83
|
+
success('Init command completed');
|
|
84
|
+
} catch (err) {
|
|
85
|
+
error('Init command failed');
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
step('🔍 Verifying project structure...');
|
|
90
|
+
|
|
91
|
+
const expectedFiles = [
|
|
92
|
+
'package.json',
|
|
93
|
+
'vitest.config.js',
|
|
94
|
+
'tests/example.test.js',
|
|
95
|
+
'tests/login.js',
|
|
96
|
+
'.env',
|
|
97
|
+
'.gitignore',
|
|
98
|
+
'.github/workflows/testdriver.yml'
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
for (const file of expectedFiles) {
|
|
102
|
+
const filePath = path.join(testDir, file);
|
|
103
|
+
if (!fs.existsSync(filePath)) {
|
|
104
|
+
error(`Missing file: ${file}`);
|
|
105
|
+
throw new Error(`Expected file not found: ${file}`);
|
|
106
|
+
}
|
|
107
|
+
success(`Found: ${file}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
step('📝 Verifying vitest.config.js contents...');
|
|
111
|
+
const vitestConfig = fs.readFileSync(path.join(testDir, 'vitest.config.js'), 'utf8');
|
|
112
|
+
|
|
113
|
+
if (!vitestConfig.includes('TestDriver()')) {
|
|
114
|
+
error('TestDriver reporter not found in vitest.config.js');
|
|
115
|
+
console.log(vitestConfig);
|
|
116
|
+
throw new Error('TestDriver reporter not configured');
|
|
117
|
+
}
|
|
118
|
+
success('TestDriver reporter is configured');
|
|
119
|
+
|
|
120
|
+
if (!vitestConfig.includes('setupFiles') || !vitestConfig.includes('testdriverai/vitest/setup')) {
|
|
121
|
+
error('setupFiles not configured correctly');
|
|
122
|
+
console.log(vitestConfig);
|
|
123
|
+
throw new Error('setupFiles not configured');
|
|
124
|
+
}
|
|
125
|
+
success('setupFiles is configured correctly');
|
|
126
|
+
|
|
127
|
+
if (!vitestConfig.includes('reporters')) {
|
|
128
|
+
error('reporters array not found');
|
|
129
|
+
console.log(vitestConfig);
|
|
130
|
+
throw new Error('reporters not configured');
|
|
131
|
+
}
|
|
132
|
+
success('reporters array includes TestDriver');
|
|
133
|
+
|
|
134
|
+
step('📝 Verifying example test contents...');
|
|
135
|
+
const testFile = fs.readFileSync(path.join(testDir, 'tests/example.test.js'), 'utf8');
|
|
136
|
+
|
|
137
|
+
if (!testFile.includes('.provision.chrome')) {
|
|
138
|
+
error('Test does not use .provision.chrome');
|
|
139
|
+
console.log(testFile);
|
|
140
|
+
throw new Error('Test does not use .provision pattern');
|
|
141
|
+
}
|
|
142
|
+
success('Test uses .provision.chrome');
|
|
143
|
+
|
|
144
|
+
if (!testFile.includes("from 'testdriverai/vitest/hooks'")) {
|
|
145
|
+
error('Test does not import from testdriverai/vitest/hooks');
|
|
146
|
+
console.log(testFile);
|
|
147
|
+
throw new Error('Test does not import TestDriver from vitest/hooks');
|
|
148
|
+
}
|
|
149
|
+
success('Test imports TestDriver from vitest/hooks');
|
|
150
|
+
|
|
151
|
+
if (!testFile.includes("from './login.js'")) {
|
|
152
|
+
error('Test does not import login from ./login.js');
|
|
153
|
+
console.log(testFile);
|
|
154
|
+
throw new Error('Test does not import login snippet');
|
|
155
|
+
}
|
|
156
|
+
success('Test imports login snippet');
|
|
157
|
+
|
|
158
|
+
step('📝 Verifying login snippet contents...');
|
|
159
|
+
const loginFile = fs.readFileSync(path.join(testDir, 'tests/login.js'), 'utf8');
|
|
160
|
+
|
|
161
|
+
if (!loginFile.includes('.extract(')) {
|
|
162
|
+
error('Login snippet does not use .extract()');
|
|
163
|
+
console.log(loginFile);
|
|
164
|
+
throw new Error('Login snippet does not demonstrate .extract()');
|
|
165
|
+
}
|
|
166
|
+
success('Login snippet demonstrates .extract()');
|
|
167
|
+
|
|
168
|
+
if (!loginFile.includes('secret: true')) {
|
|
169
|
+
error('Login snippet does not use secret option');
|
|
170
|
+
console.log(loginFile);
|
|
171
|
+
throw new Error('Login snippet does not demonstrate secret typing');
|
|
172
|
+
}
|
|
173
|
+
success('Login snippet demonstrates secret typing');
|
|
174
|
+
|
|
175
|
+
step('🧪 Running generated test...');
|
|
176
|
+
try {
|
|
177
|
+
execSync('npm test', {
|
|
178
|
+
cwd: testDir,
|
|
179
|
+
stdio: 'inherit',
|
|
180
|
+
env: { ...process.env, TD_API_KEY: process.env.TD_API_KEY }
|
|
181
|
+
});
|
|
182
|
+
success('Test execution completed successfully');
|
|
183
|
+
} catch (err) {
|
|
184
|
+
error('Test execution failed');
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
step('✅ All checks passed!');
|
|
189
|
+
log('\nTest summary:', 'green');
|
|
190
|
+
log(' • Init command executed successfully', 'green');
|
|
191
|
+
log(' • All expected files created', 'green');
|
|
192
|
+
log(' • Configuration files are correct', 'green');
|
|
193
|
+
log(' • Example test has proper patterns', 'green');
|
|
194
|
+
log(' • Generated test runs successfully', 'green');
|
|
195
|
+
|
|
196
|
+
} catch (err) {
|
|
197
|
+
step('❌ Test failed!');
|
|
198
|
+
error(err.message);
|
|
199
|
+
if (err.stack) {
|
|
200
|
+
log(err.stack, 'gray');
|
|
201
|
+
}
|
|
202
|
+
process.exit(1);
|
|
203
|
+
} finally {
|
|
204
|
+
// Optional: Clean up test directory
|
|
205
|
+
// Commented out so you can inspect the generated files
|
|
206
|
+
// step('🧹 Cleaning up...');
|
|
207
|
+
// if (fs.existsSync(testDir)) {
|
|
208
|
+
// fs.rmSync(testDir, { recursive: true, force: true });
|
|
209
|
+
// success('Cleaned up test directory');
|
|
210
|
+
// }
|
|
211
|
+
|
|
212
|
+
info(`\nTest project preserved at: ${testDir}`);
|
|
213
|
+
info('To clean up manually, run:');
|
|
214
|
+
log(` rm -rf ${testDir}`, 'gray');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Run the test
|
|
219
|
+
testInitCommand().catch(err => {
|
|
220
|
+
error('Unexpected error:');
|
|
221
|
+
console.error(err);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testdriverai",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.4",
|
|
4
4
|
"description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
|
|
5
5
|
"main": "sdk.js",
|
|
6
6
|
"exports": {
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@eslint/js": "^9.10.0",
|
|
88
|
-
"@vitest/ui": "^4.0.
|
|
88
|
+
"@vitest/ui": "^4.0.15",
|
|
89
89
|
"chai": "^5.1.2",
|
|
90
90
|
"esbuild": "0.20.2",
|
|
91
91
|
"esbuild-plugin-fileloc": "^0.0.6",
|
package/schema.json
CHANGED
|
@@ -618,7 +618,7 @@
|
|
|
618
618
|
}
|
|
619
619
|
}
|
|
620
620
|
},
|
|
621
|
-
"
|
|
621
|
+
"extract": {
|
|
622
622
|
"type": "object",
|
|
623
623
|
"required": [
|
|
624
624
|
"description",
|
|
@@ -628,7 +628,7 @@
|
|
|
628
628
|
"properties": {
|
|
629
629
|
"command": {
|
|
630
630
|
"type": "string",
|
|
631
|
-
"const": "
|
|
631
|
+
"const": "extract"
|
|
632
632
|
},
|
|
633
633
|
"description": {
|
|
634
634
|
"type": "string"
|
|
@@ -783,7 +783,7 @@
|
|
|
783
783
|
"scroll-until-text",
|
|
784
784
|
"scroll-until-image",
|
|
785
785
|
"focus-application",
|
|
786
|
-
"
|
|
786
|
+
"extract",
|
|
787
787
|
"assert",
|
|
788
788
|
"exec",
|
|
789
789
|
"if",
|
|
@@ -971,12 +971,12 @@
|
|
|
971
971
|
"if": {
|
|
972
972
|
"properties": {
|
|
973
973
|
"command": {
|
|
974
|
-
"const": "
|
|
974
|
+
"const": "extract"
|
|
975
975
|
}
|
|
976
976
|
}
|
|
977
977
|
},
|
|
978
978
|
"then": {
|
|
979
|
-
"$ref": "#/$defs/commandsAvailable/
|
|
979
|
+
"$ref": "#/$defs/commandsAvailable/extract"
|
|
980
980
|
}
|
|
981
981
|
},
|
|
982
982
|
{
|
package/sdk-log-formatter.js
CHANGED
package/sdk.d.ts
CHANGED
|
@@ -433,9 +433,9 @@ export interface FocusApplicationOptions {
|
|
|
433
433
|
name: string;
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
/** Options for
|
|
437
|
-
export interface
|
|
438
|
-
/** What to
|
|
436
|
+
/** Options for extract command */
|
|
437
|
+
export interface ExtractOptions {
|
|
438
|
+
/** What to extract */
|
|
439
439
|
description: string;
|
|
440
440
|
}
|
|
441
441
|
|
|
@@ -919,15 +919,15 @@ export default class TestDriverSDK {
|
|
|
919
919
|
assert(assertion: string, options?: object): Promise<boolean>;
|
|
920
920
|
|
|
921
921
|
/**
|
|
922
|
-
* Extract
|
|
922
|
+
* Extract information from the screen using AI
|
|
923
923
|
* @param options - Options object with description
|
|
924
924
|
*/
|
|
925
|
-
|
|
925
|
+
extract(options: { description: string }): Promise<string>;
|
|
926
926
|
/**
|
|
927
|
-
* Extract
|
|
928
|
-
* @param description - What to
|
|
927
|
+
* Extract information from the screen using AI (positional arguments - legacy)
|
|
928
|
+
* @param description - What to extract
|
|
929
929
|
*/
|
|
930
|
-
|
|
930
|
+
extract(description: string): Promise<string>;
|
|
931
931
|
|
|
932
932
|
// Code Execution
|
|
933
933
|
|
package/sdk.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// Auto-load environment variables from .env file if it exists
|
|
2
|
-
require("dotenv").config();
|
|
3
|
-
|
|
4
1
|
const fs = require("fs");
|
|
5
2
|
const path = require("path");
|
|
6
3
|
const os = require("os");
|
|
@@ -342,12 +339,12 @@ class Element {
|
|
|
342
339
|
}
|
|
343
340
|
|
|
344
341
|
// Determine threshold:
|
|
345
|
-
// - If cacheKey is provided, enable cache (threshold = 0.
|
|
342
|
+
// - If cacheKey is provided, enable cache (threshold = 0.01 or custom)
|
|
346
343
|
// - If no cacheKey, disable cache (threshold = -1) unless explicitly overridden
|
|
347
344
|
let threshold;
|
|
348
345
|
if (cacheKey) {
|
|
349
346
|
// cacheKey provided - enable cache with threshold
|
|
350
|
-
threshold = cacheThreshold ?? 0.
|
|
347
|
+
threshold = cacheThreshold ?? 0.01;
|
|
351
348
|
} else if (cacheThreshold !== null) {
|
|
352
349
|
// Explicit threshold provided without cacheKey
|
|
353
350
|
threshold = cacheThreshold;
|
|
@@ -1258,11 +1255,65 @@ class TestDriverSDK {
|
|
|
1258
1255
|
console.log('[provision.chrome] ✅ Dashcam started');
|
|
1259
1256
|
}
|
|
1260
1257
|
|
|
1258
|
+
// Set up Chrome profile with preferences
|
|
1259
|
+
const shell = this.os === 'windows' ? 'pwsh' : 'sh';
|
|
1260
|
+
const userDataDir = this.os === 'windows'
|
|
1261
|
+
? 'C:\\Users\\testdriver\\AppData\\Local\\TestDriver\\Chrome'
|
|
1262
|
+
: '/tmp/testdriver-chrome-profile';
|
|
1263
|
+
|
|
1264
|
+
// Create user data directory and Default profile directory
|
|
1265
|
+
const defaultProfileDir = this.os === 'windows'
|
|
1266
|
+
? `${userDataDir}\\Default`
|
|
1267
|
+
: `${userDataDir}/Default`;
|
|
1268
|
+
|
|
1269
|
+
const createDirCmd = this.os === 'windows'
|
|
1270
|
+
? `New-Item -ItemType Directory -Path "${defaultProfileDir}" -Force | Out-Null`
|
|
1271
|
+
: `mkdir -p "${defaultProfileDir}"`;
|
|
1272
|
+
|
|
1273
|
+
await this.exec(shell, createDirCmd, 10000, true);
|
|
1274
|
+
|
|
1275
|
+
// Write Chrome preferences
|
|
1276
|
+
const chromePrefs = {
|
|
1277
|
+
credentials_enable_service: false,
|
|
1278
|
+
profile: {
|
|
1279
|
+
password_manager_enabled: false,
|
|
1280
|
+
default_content_setting_values: {}
|
|
1281
|
+
},
|
|
1282
|
+
signin: {
|
|
1283
|
+
allowed: false
|
|
1284
|
+
},
|
|
1285
|
+
sync: {
|
|
1286
|
+
requested: false,
|
|
1287
|
+
first_setup_complete: true,
|
|
1288
|
+
sync_all_os_types: false
|
|
1289
|
+
},
|
|
1290
|
+
autofill: {
|
|
1291
|
+
enabled: false
|
|
1292
|
+
},
|
|
1293
|
+
local_state: {
|
|
1294
|
+
browser: {
|
|
1295
|
+
has_seen_welcome_page: true
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1300
|
+
const prefsPath = this.os === 'windows'
|
|
1301
|
+
? `${defaultProfileDir}\\Preferences`
|
|
1302
|
+
: `${defaultProfileDir}/Preferences`;
|
|
1303
|
+
|
|
1304
|
+
const prefsJson = JSON.stringify(chromePrefs, null, 2);
|
|
1305
|
+
const writePrefCmd = this.os === 'windows'
|
|
1306
|
+
? `Set-Content -Path "${prefsPath}" -Value '${prefsJson.replace(/'/g, "''")}'`
|
|
1307
|
+
: `cat > "${prefsPath}" << 'EOF'\n${prefsJson}\nEOF`;
|
|
1308
|
+
|
|
1309
|
+
await this.exec(shell, writePrefCmd, 10000, true);
|
|
1310
|
+
console.log('[provision.chrome] ✅ Chrome preferences configured');
|
|
1311
|
+
|
|
1261
1312
|
// Build Chrome launch command
|
|
1262
1313
|
const chromeArgs = [];
|
|
1263
1314
|
if (maximized) chromeArgs.push('--start-maximized');
|
|
1264
1315
|
if (guest) chromeArgs.push('--guest');
|
|
1265
|
-
chromeArgs.push('--disable-fre', '--no-default-browser-check', '--no-first-run');
|
|
1316
|
+
chromeArgs.push('--disable-fre', '--no-default-browser-check', '--no-first-run', '--disable-infobars', `--user-data-dir=${userDataDir}`);
|
|
1266
1317
|
|
|
1267
1318
|
// Add dashcam-chrome extension on Linux
|
|
1268
1319
|
if (this.os === 'linux') {
|
|
@@ -1270,7 +1321,6 @@ class TestDriverSDK {
|
|
|
1270
1321
|
}
|
|
1271
1322
|
|
|
1272
1323
|
// Launch Chrome
|
|
1273
|
-
const shell = this.os === 'windows' ? 'pwsh' : 'sh';
|
|
1274
1324
|
|
|
1275
1325
|
if (this.os === 'windows') {
|
|
1276
1326
|
const argsString = chromeArgs.map(arg => `"${arg}"`).join(', ');
|
|
@@ -1668,12 +1718,12 @@ class TestDriverSDK {
|
|
|
1668
1718
|
}
|
|
1669
1719
|
|
|
1670
1720
|
// Determine threshold:
|
|
1671
|
-
// - If cacheKey is provided, enable cache (threshold = 0.
|
|
1721
|
+
// - If cacheKey is provided, enable cache (threshold = 0.01 or custom)
|
|
1672
1722
|
// - If no cacheKey, disable cache (threshold = -1) unless explicitly overridden
|
|
1673
1723
|
let threshold;
|
|
1674
1724
|
if (cacheKey) {
|
|
1675
1725
|
// cacheKey provided - enable cache with threshold
|
|
1676
|
-
threshold = cacheThreshold ?? 0.
|
|
1726
|
+
threshold = cacheThreshold ?? 0.01;
|
|
1677
1727
|
} else if (cacheThreshold !== null) {
|
|
1678
1728
|
// Explicit threshold provided without cacheKey
|
|
1679
1729
|
threshold = cacheThreshold;
|
|
@@ -2051,15 +2101,15 @@ class TestDriverSDK {
|
|
|
2051
2101
|
*/
|
|
2052
2102
|
doc: "Focus an application by name",
|
|
2053
2103
|
},
|
|
2054
|
-
|
|
2055
|
-
name: "
|
|
2104
|
+
extract: {
|
|
2105
|
+
name: "extract",
|
|
2056
2106
|
/**
|
|
2057
|
-
* Extract
|
|
2107
|
+
* Extract information from the screen using AI
|
|
2058
2108
|
* @param {Object|string} options - Options object or description (legacy positional)
|
|
2059
|
-
* @param {string} options.description - What to
|
|
2109
|
+
* @param {string} options.description - What to extract
|
|
2060
2110
|
* @returns {Promise<string>}
|
|
2061
2111
|
*/
|
|
2062
|
-
doc: "Extract
|
|
2112
|
+
doc: "Extract information from the screen",
|
|
2063
2113
|
},
|
|
2064
2114
|
assert: {
|
|
2065
2115
|
name: "assert",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
8
|
|
|
9
|
-
describe.
|
|
9
|
+
describe.skip("Exec Output Test", () => {
|
|
10
10
|
it(
|
|
11
11
|
"should set date using PowerShell and navigate to calendar",
|
|
12
12
|
async (context) => {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
8
|
|
|
9
|
-
describe.
|
|
9
|
+
describe.skip("Exec PowerShell Test", () => {
|
|
10
10
|
it(
|
|
11
11
|
"should generate random email using PowerShell and enter it",
|
|
12
12
|
async (context) => {
|
|
@@ -7,7 +7,7 @@ import { describe, expect, it } from "vitest";
|
|
|
7
7
|
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
8
|
|
|
9
9
|
describe("Focus Window Test", () => {
|
|
10
|
-
it.
|
|
10
|
+
it.skip(
|
|
11
11
|
"should click Microsoft Edge icon and focus Google Chrome",
|
|
12
12
|
async (context) => {
|
|
13
13
|
const testdriver = TestDriver(context, { headless: true });
|
|
@@ -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: false });
|
|
13
13
|
|
|
14
14
|
// provision.chrome() automatically calls ready() and starts dashcam
|
|
15
15
|
await testdriver.provision.chrome({
|
|
@@ -17,21 +17,18 @@ describe("Hover Text With Description Test", () => {
|
|
|
17
17
|
await performLogin(testdriver);
|
|
18
18
|
|
|
19
19
|
// Click on "Add to Cart" under TestDriver Hat
|
|
20
|
-
await testdriver.focusApplication("Google Chrome");
|
|
21
20
|
const addToCartButton = await testdriver.find(
|
|
22
21
|
"Add to Cart, add to cart button under TestDriver Hat",
|
|
23
22
|
);
|
|
24
23
|
await addToCartButton.click();
|
|
25
24
|
|
|
26
25
|
// Click on the cart
|
|
27
|
-
await testdriver.focusApplication("Google Chrome");
|
|
28
26
|
const cartButton = await testdriver.find(
|
|
29
27
|
"Cart, cart button in the top right corner",
|
|
30
28
|
);
|
|
31
29
|
await cartButton.click();
|
|
32
30
|
|
|
33
31
|
// Assert the TestDriver Hat is in the cart
|
|
34
|
-
await testdriver.focusApplication("Google Chrome");
|
|
35
32
|
const result = await testdriver.assert("TestDriver Hat is in the cart");
|
|
36
33
|
expect(result).toBeTruthy();
|
|
37
34
|
});
|
|
@@ -14,7 +14,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
14
14
|
const __dirname = dirname(__filename);
|
|
15
15
|
|
|
16
16
|
describe("Match Image Test", () => {
|
|
17
|
-
it("should match shopping cart image and verify empty cart", async (context) => {
|
|
17
|
+
it.skip("should match shopping cart image and verify empty cart", async (context) => {
|
|
18
18
|
const testdriver = TestDriver(context, { headless: true });
|
|
19
19
|
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
20
20
|
|
|
@@ -27,7 +27,7 @@ describe("Scroll Keyboard Test", () => {
|
|
|
27
27
|
"The Hamster Dance, large heading at top of page",
|
|
28
28
|
);
|
|
29
29
|
await heading.click();
|
|
30
|
-
await testdriver.scroll("down", 1000);
|
|
30
|
+
await testdriver.scroll("down", { amount: 1000 });
|
|
31
31
|
|
|
32
32
|
// Assert the page is scrolled down
|
|
33
33
|
const result = await testdriver.assert(
|
|
@@ -7,7 +7,7 @@ import { describe, expect, it } from "vitest";
|
|
|
7
7
|
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
8
|
|
|
9
9
|
describe("Scroll Until Image Test", () => {
|
|
10
|
-
it("should scroll until brown colored house image appears", async (context) => {
|
|
10
|
+
it.skip("should scroll until brown colored house image appears", async (context) => {
|
|
11
11
|
const testdriver = TestDriver(context, { headless: true });
|
|
12
12
|
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
13
13
|
|
|
@@ -18,7 +18,24 @@ describe("Scroll Until Text Test", () => {
|
|
|
18
18
|
|
|
19
19
|
// Scroll until text appears
|
|
20
20
|
await testdriver.focusApplication("Google Chrome");
|
|
21
|
-
|
|
21
|
+
// Scroll until text appears
|
|
22
|
+
let found = false;
|
|
23
|
+
let scrollCount = 0;
|
|
24
|
+
const maxScrolls = 10;
|
|
25
|
+
|
|
26
|
+
while (!found && scrollCount < maxScrolls) {
|
|
27
|
+
const findResult = await testdriver.find("testdriver socks");
|
|
28
|
+
if (findResult) {
|
|
29
|
+
found = true;
|
|
30
|
+
} else {
|
|
31
|
+
await testdriver.scroll({ direction: "down" });
|
|
32
|
+
scrollCount++;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!found) {
|
|
37
|
+
throw new Error(`Failed to find "testdriver socks" after ${maxScrolls} scrolls`);
|
|
38
|
+
}
|
|
22
39
|
|
|
23
40
|
// Assert testdriver socks appears on screen
|
|
24
41
|
await testdriver.focusApplication("Google Chrome");
|
|
@@ -32,7 +32,7 @@ describe("Scroll Test", () => {
|
|
|
32
32
|
await heading.click();
|
|
33
33
|
|
|
34
34
|
// Scroll down
|
|
35
|
-
await testdriver.scroll("down", 1000);
|
|
35
|
+
await testdriver.scroll("down", { amount: 1000 });
|
|
36
36
|
|
|
37
37
|
// Assert page is scrolled
|
|
38
38
|
const result = await testdriver.assert("the page is scrolled down, the hamster dance heading is not visible on the page");
|