testdriverai 7.3.3 → 7.3.5
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-linux-scheduled.yaml +1 -1
- package/.github/workflows/acceptance.yaml +38 -1
- package/.github/workflows/windows-self-hosted.yaml +9 -1
- package/CHANGELOG.md +8 -0
- package/docs/_data/examples-manifest.json +105 -0
- package/docs/_data/examples-manifest.schema.json +41 -0
- package/docs/_scripts/extract-example-urls.js +165 -0
- package/docs/_scripts/generate-examples.js +534 -0
- package/docs/docs.json +242 -212
- package/docs/v7/aws-setup.mdx +1 -1
- package/docs/v7/examples/ai.mdx +72 -0
- package/docs/v7/examples/assert.mdx +72 -0
- package/docs/v7/examples/captcha-api.mdx +92 -0
- package/docs/v7/examples/chrome-extension.mdx +132 -0
- package/docs/v7/examples/drag-and-drop.mdx +100 -0
- package/docs/v7/examples/element-not-found.mdx +67 -0
- package/docs/v7/examples/hover-image.mdx +94 -0
- package/docs/v7/examples/hover-text.mdx +69 -0
- package/docs/v7/examples/installer.mdx +91 -0
- package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
- package/docs/v7/examples/match-image.mdx +96 -0
- package/docs/v7/examples/press-keys.mdx +92 -0
- package/docs/v7/examples/scroll-keyboard.mdx +79 -0
- package/docs/v7/examples/scroll-until-image.mdx +81 -0
- package/docs/v7/examples/scroll-until-text.mdx +109 -0
- package/docs/v7/examples/scroll.mdx +81 -0
- package/docs/v7/examples/type.mdx +92 -0
- package/docs/v7/examples/windows-installer.mdx +89 -0
- package/interfaces/vitest-plugin.mjs +50 -18
- package/package.json +3 -1
- package/docs/v7/examples.mdx +0 -5
- package/jsconfig.json +0 -26
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Typing Test Example"
|
|
3
|
+
sidebarTitle: "Typing"
|
|
4
|
+
description: "Example test demonstrating how to type text into input fields and verify the content."
|
|
5
|
+
icon: "keyboard"
|
|
6
|
+
mode: "wide"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Demo Test Run
|
|
10
|
+
|
|
11
|
+
Watch this test execute in a real sandbox environment:
|
|
12
|
+
|
|
13
|
+
{/* type.test.mjs output */}
|
|
14
|
+
<iframe
|
|
15
|
+
src="https://testdriver-api.onrender.com/api/v1/testdriver/testcase/69852d10eae78746d7ac0c2e/replay"
|
|
16
|
+
width="100%"
|
|
17
|
+
height="390"
|
|
18
|
+
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
19
|
+
allow="fullscreen"
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
## Source Code
|
|
23
|
+
|
|
24
|
+
```javascript title="type.test.mjs" {13}
|
|
25
|
+
/**
|
|
26
|
+
* TestDriver SDK - Type Test
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { describe, expect, it } from "vitest";
|
|
30
|
+
import { TestDriver } from "../lib/vitest/hooks.mjs";
|
|
31
|
+
|
|
32
|
+
describe("Type Test", () => {
|
|
33
|
+
it("should enter standard_user in username field", async (context) => {
|
|
34
|
+
const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
|
|
35
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
36
|
+
|
|
37
|
+
//
|
|
38
|
+
const usernameField = await testdriver.find(
|
|
39
|
+
"Username, input field for username",
|
|
40
|
+
);
|
|
41
|
+
await usernameField.click();
|
|
42
|
+
await testdriver.type("standard_user");
|
|
43
|
+
|
|
44
|
+
const result = await testdriver.assert(
|
|
45
|
+
'the username field contains "standard_user"',
|
|
46
|
+
);
|
|
47
|
+
expect(result).toBeTruthy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should show validation message when clicking Sign In without password", async (context) => {
|
|
51
|
+
const testdriver = TestDriver(context, { ip: context.ip || process.env.TD_IP, headless: true });
|
|
52
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
53
|
+
|
|
54
|
+
// First fill in username
|
|
55
|
+
const usernameField = await testdriver.find(
|
|
56
|
+
"Username, input field for username",
|
|
57
|
+
);
|
|
58
|
+
await usernameField.click();
|
|
59
|
+
await testdriver.type("standard_user");
|
|
60
|
+
|
|
61
|
+
//
|
|
62
|
+
const signInButton = await testdriver.find(
|
|
63
|
+
"Sign in, black button below the password field",
|
|
64
|
+
);
|
|
65
|
+
await signInButton.click();
|
|
66
|
+
|
|
67
|
+
await testdriver.focusApplication("Google Chrome");
|
|
68
|
+
const result = await testdriver.assert(
|
|
69
|
+
"Please fill out this field is visible near the password field",
|
|
70
|
+
);
|
|
71
|
+
expect(result).toBeTruthy();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Running This Example
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Clone the TestDriver repository
|
|
80
|
+
git clone https://github.com/testdriverai/testdriverai
|
|
81
|
+
|
|
82
|
+
# Install dependencies
|
|
83
|
+
cd testdriverai
|
|
84
|
+
npm install
|
|
85
|
+
|
|
86
|
+
# Run this specific example
|
|
87
|
+
npx vitest run examples/type.test.mjs
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
<Note>
|
|
91
|
+
Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
|
|
92
|
+
</Note>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Windows App Installation"
|
|
3
|
+
sidebarTitle: "Windows Installer"
|
|
4
|
+
description: "Example test showing how to download and install Windows applications using MSI installers."
|
|
5
|
+
icon: "download"
|
|
6
|
+
mode: "wide"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Demo Test Run
|
|
10
|
+
|
|
11
|
+
Watch this test execute in a real sandbox environment:
|
|
12
|
+
|
|
13
|
+
{/* windows-installer.test.mjs output */}
|
|
14
|
+
<iframe
|
|
15
|
+
src="https://testdriver-api.onrender.com/api/v1/testdriver/testcase/69852931eae78746d7ac0be6/replay"
|
|
16
|
+
width="100%"
|
|
17
|
+
height="390"
|
|
18
|
+
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
19
|
+
allow="fullscreen"
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
## Source Code
|
|
23
|
+
|
|
24
|
+
```javascript title="windows-installer.test.mjs" {22-25}
|
|
25
|
+
/**
|
|
26
|
+
* TestDriver SDK - Windows Installer Example
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { describe, it } from "vitest";
|
|
30
|
+
import { TestDriver } from "../lib/vitest/hooks.mjs";
|
|
31
|
+
|
|
32
|
+
const isLinux = (process.env.TD_OS || "linux") === "linux";
|
|
33
|
+
|
|
34
|
+
describe("Windows App Installation", () => {
|
|
35
|
+
|
|
36
|
+
it.skipIf(isLinux)("should download, install, and launch GitButler on Windows", async (context) => {
|
|
37
|
+
// Alternative approach using provision.installer helper
|
|
38
|
+
const testdriver = TestDriver(context, {
|
|
39
|
+
ip: context.ip || process.env.TD_IP,
|
|
40
|
+
os: 'windows'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Download the MSI installer
|
|
44
|
+
const installerPath = await testdriver.provision.installer({
|
|
45
|
+
url: 'https://app.gitbutler.com/downloads/release/windows/x86_64/msi',
|
|
46
|
+
launch: false, // Don't auto-launch, we'll install manually
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log('Installer downloaded to:', installerPath);
|
|
50
|
+
|
|
51
|
+
// Install the MSI silently (the file might not have an extension, so we try MSI first)
|
|
52
|
+
await testdriver.exec('pwsh',
|
|
53
|
+
`Start-Process msiexec.exe -ArgumentList "/i \`"${installerPath}\`" /qn /norestart" -Wait`,
|
|
54
|
+
120000
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Verify installation by checking if executable exists
|
|
58
|
+
const verifyScript = `
|
|
59
|
+
$exePath = "C:\\Program Files\\GitButler\\gitbutler-tauri.exe"
|
|
60
|
+
if (Test-Path $exePath) {
|
|
61
|
+
Write-Host "GitButler installed successfully at $exePath"
|
|
62
|
+
} else {
|
|
63
|
+
Write-Error "GitButler not found"
|
|
64
|
+
exit 1
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
await testdriver.exec('pwsh', verifyScript, 5000);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Running This Example
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Clone the TestDriver repository
|
|
77
|
+
git clone https://github.com/testdriverai/testdriverai
|
|
78
|
+
|
|
79
|
+
# Install dependencies
|
|
80
|
+
cd testdriverai
|
|
81
|
+
npm install
|
|
82
|
+
|
|
83
|
+
# Run this specific example
|
|
84
|
+
npx vitest run examples/windows-installer.test.mjs
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<Note>
|
|
88
|
+
Make sure you have `TD_API_KEY` set in your environment. Get one at [testdriver.ai](https://testdriver.ai).
|
|
89
|
+
</Note>
|
|
@@ -14,30 +14,54 @@ const require = createRequire(import.meta.url);
|
|
|
14
14
|
*/
|
|
15
15
|
const MINIMUM_VITEST_VERSION = 4;
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Try to read vitest's package.json version using multiple resolution strategies.
|
|
19
|
+
* Vitest's Vite-based transform pipeline can rewrite import.meta.url, causing
|
|
20
|
+
* createRequire to resolve from the wrong location. We fall back to resolving
|
|
21
|
+
* from process.cwd() and then to reading directly from node_modules.
|
|
22
|
+
* @returns {string|null} The vitest version string, or null if not found
|
|
23
|
+
*/
|
|
24
|
+
function resolveVitestVersion() {
|
|
25
|
+
// Strategy 1: createRequire from import.meta.url (standard CJS interop)
|
|
26
|
+
try {
|
|
27
|
+
return require("vitest/package.json").version;
|
|
28
|
+
} catch {}
|
|
29
|
+
|
|
30
|
+
// Strategy 2: createRequire from process.cwd() (works when import.meta.url is rewritten)
|
|
31
|
+
try {
|
|
32
|
+
const cwdRequire = createRequire(path.join(process.cwd(), "package.json"));
|
|
33
|
+
return cwdRequire("vitest/package.json").version;
|
|
34
|
+
} catch {}
|
|
35
|
+
|
|
36
|
+
// Strategy 3: read directly from node_modules on disk
|
|
37
|
+
try {
|
|
38
|
+
const vitestPkgPath = path.join(process.cwd(), "node_modules", "vitest", "package.json");
|
|
39
|
+
return JSON.parse(fs.readFileSync(vitestPkgPath, "utf8")).version;
|
|
40
|
+
} catch {}
|
|
41
|
+
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
17
45
|
/**
|
|
18
46
|
* Check that Vitest version meets minimum requirements
|
|
19
47
|
* @throws {Error} if Vitest version is below minimum or not installed
|
|
20
48
|
*/
|
|
21
49
|
function checkVitestVersion() {
|
|
22
|
-
|
|
23
|
-
const vitestPkg = require("vitest/package.json");
|
|
24
|
-
const version = vitestPkg.version;
|
|
25
|
-
const major = parseInt(version.split(".")[0], 10);
|
|
50
|
+
const version = resolveVitestVersion();
|
|
26
51
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
throw err;
|
|
52
|
+
if (!version) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
"TestDriver requires Vitest to be installed. " +
|
|
55
|
+
"Please install it: npm install vitest@latest",
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const major = parseInt(version.split(".")[0], 10);
|
|
60
|
+
if (major < MINIMUM_VITEST_VERSION) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`TestDriver requires Vitest >= ${MINIMUM_VITEST_VERSION}.0.0, but found ${version}. ` +
|
|
63
|
+
`Please upgrade Vitest: npm install vitest@latest`,
|
|
64
|
+
);
|
|
41
65
|
}
|
|
42
66
|
}
|
|
43
67
|
|
|
@@ -1013,6 +1037,14 @@ class TestDriverReporter {
|
|
|
1013
1037
|
console.log(
|
|
1014
1038
|
`🔗 Test Report: ${getConsoleUrl(pluginState.apiRoot)}/runs/${testRunDbId}/${testCaseDbId}`,
|
|
1015
1039
|
);
|
|
1040
|
+
|
|
1041
|
+
// Output parseable format for docs generation (examples only)
|
|
1042
|
+
if (testFile.startsWith("examples/")) {
|
|
1043
|
+
const testFileName = path.basename(testFile);
|
|
1044
|
+
console.log(
|
|
1045
|
+
`TESTDRIVER_EXAMPLE_URL::${testFileName}::${getConsoleUrl(pluginState.apiRoot)}/runs/${testRunDbId}/${testCaseDbId}`,
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1016
1048
|
} catch (error) {
|
|
1017
1049
|
logger.error("Failed to report test case:", error.message);
|
|
1018
1050
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testdriverai",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.5",
|
|
4
4
|
"description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
|
|
5
5
|
"main": "sdk.js",
|
|
6
6
|
"types": "sdk.d.ts",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
"docs:build": "npm run docs:skills && cd docs && npx mint@latest build",
|
|
43
43
|
"docs:links": "node docs/_scripts/link-replacer.js",
|
|
44
44
|
"docs:skills": "node docs/_scripts/generate-skills.js",
|
|
45
|
+
"docs:examples": "node docs/_scripts/generate-examples.js",
|
|
46
|
+
"docs:extract-urls": "node docs/_scripts/extract-example-urls.js",
|
|
45
47
|
"bundle": "node build.mjs",
|
|
46
48
|
"test": "mocha test/*",
|
|
47
49
|
"test:sdk": "vitest run",
|
package/docs/v7/examples.mdx
DELETED
package/jsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "ESNext",
|
|
4
|
-
"moduleResolution": "bundler",
|
|
5
|
-
"target": "ES2022",
|
|
6
|
-
"checkJs": true,
|
|
7
|
-
"strict": false,
|
|
8
|
-
"allowSyntheticDefaultImports": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"baseUrl": ".",
|
|
11
|
-
"typeRoots": ["."]
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"**/*.js",
|
|
15
|
-
"**/*.mjs",
|
|
16
|
-
"**/*.d.ts",
|
|
17
|
-
"sdk.d.ts",
|
|
18
|
-
"lib/**/*.d.ts",
|
|
19
|
-
"interfaces/**/*.d.ts"
|
|
20
|
-
],
|
|
21
|
-
"exclude": [
|
|
22
|
-
"node_modules",
|
|
23
|
-
"dist",
|
|
24
|
-
"build"
|
|
25
|
-
]
|
|
26
|
-
}
|