testdriverai 7.0.0 → 7.1.0
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/AGENTS.md +550 -0
- package/CODEOWNERS +0 -1
- package/README.md +126 -0
- package/agent/index.js +43 -18
- package/agent/lib/commands.js +794 -135
- package/agent/lib/redraw.js +124 -39
- package/agent/lib/sandbox.js +10 -1
- package/agent/lib/sdk.js +21 -0
- package/docs/MIGRATION.md +425 -0
- package/docs/PRESETS.md +210 -0
- package/docs/docs.json +91 -37
- package/docs/guide/best-practices-polling.mdx +154 -0
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/getting-started/configuration.mdx +380 -0
- package/docs/v7/getting-started/quickstart.mdx +273 -140
- package/docs/v7/guides/best-practices.mdx +486 -0
- package/docs/v7/guides/caching-ai.mdx +215 -0
- package/docs/v7/guides/caching-selectors.mdx +292 -0
- package/docs/v7/guides/caching.mdx +366 -0
- package/docs/v7/guides/ci-cd/azure.mdx +587 -0
- package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
- package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
- package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
- package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
- package/docs/v7/guides/ci-cd/travis.mdx +438 -0
- package/docs/v7/guides/debugging.mdx +349 -0
- package/docs/v7/guides/faq.mdx +393 -0
- package/docs/v7/guides/performance.mdx +517 -0
- package/docs/v7/guides/troubleshooting.mdx +526 -0
- package/docs/v7/guides/vitest-plugin.mdx +477 -0
- package/docs/v7/guides/vitest.mdx +535 -0
- package/docs/v7/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +287 -0
- package/docs/v7/presets/electron.mdx +435 -0
- package/docs/v7/presets/vscode.mdx +398 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/docs/v7/progressive-apis/CORE.md +459 -0
- package/docs/v7/progressive-apis/HOOKS.md +360 -0
- package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
- package/docs/v7/progressive-apis/PROVISION.md +266 -0
- package/interfaces/vitest-plugin.mjs +186 -100
- package/package.json +12 -1
- package/sdk.d.ts +335 -42
- package/sdk.js +756 -95
- package/src/core/Dashcam.js +469 -0
- package/src/core/index.d.ts +150 -0
- package/src/core/index.js +12 -0
- package/src/presets/index.mjs +331 -0
- package/src/vitest/extended.mjs +108 -0
- package/src/vitest/hooks.d.ts +119 -0
- package/src/vitest/hooks.mjs +298 -0
- package/src/vitest/index.mjs +64 -0
- package/src/vitest/lifecycle.mjs +277 -0
- package/src/vitest/utils.mjs +150 -0
- package/test/dashcam.test.js +137 -0
- package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
- package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
- package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
- package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
- package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
- package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
- package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
- package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
- package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
- package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
- package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
- package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
- package/testdriver/acceptance-sdk/type.test.mjs +19 -58
- package/vitest.config.mjs +1 -0
- package/.vscode/mcp.json +0 -9
- package/MIGRATION.md +0 -389
- package/PLUGIN_MIGRATION.md +0 -222
- package/PROMPT_CACHE.md +0 -200
- package/SDK_LOGGING.md +0 -222
- package/SDK_MIGRATION.md +0 -474
- package/SDK_README.md +0 -1122
- package/debug-screenshot-1763401388589.png +0 -0
- package/examples/run-tests-with-recording.sh +0 -70
- package/examples/screenshot-example.js +0 -63
- package/examples/sdk-awesome-logs-demo.js +0 -177
- package/examples/sdk-cache-thresholds.js +0 -96
- package/examples/sdk-element-properties.js +0 -155
- package/examples/sdk-simple-example.js +0 -65
- package/examples/test-recording-example.test.js +0 -166
- package/mcp-server/AI_GUIDELINES.md +0 -57
- package/test-find-api.js +0 -73
- package/test-prompt-cache.js +0 -96
- package/test-sandbox-render.js +0 -28
- package/test-sdk-methods.js +0 -15
- package/test-sdk-refactor.js +0 -53
- package/test-stack-trace.mjs +0 -57
- package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
|
Binary file
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Example script showing how to run tests with TestDriver + Dashcam integration
|
|
4
|
-
# This script demonstrates the complete flow:
|
|
5
|
-
# 1. Start dashcam
|
|
6
|
-
# 2. Run tests with Vitest reporter
|
|
7
|
-
# 3. Stop and publish dashcam recording
|
|
8
|
-
# 4. View results in TestDriver dashboard
|
|
9
|
-
|
|
10
|
-
set -e
|
|
11
|
-
|
|
12
|
-
echo "======================================"
|
|
13
|
-
echo "TestDriver + Dashcam Test Recording"
|
|
14
|
-
echo "======================================"
|
|
15
|
-
echo ""
|
|
16
|
-
|
|
17
|
-
# Check for required environment variables
|
|
18
|
-
if [ -z "$TD_API_KEY" ]; then
|
|
19
|
-
echo "Error: TD_API_KEY environment variable is required"
|
|
20
|
-
echo "Get your API key from: https://app.testdriver.ai/settings/api-keys"
|
|
21
|
-
exit 1
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
if [ -z "$DASHCAM_PROJECT_ID" ]; then
|
|
25
|
-
echo "Warning: DASHCAM_PROJECT_ID not set, replays won't be published"
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
# Start Dashcam recording
|
|
29
|
-
echo "📹 Starting Dashcam..."
|
|
30
|
-
dashcam start
|
|
31
|
-
|
|
32
|
-
# Track test logs
|
|
33
|
-
echo "📝 Tracking test output..."
|
|
34
|
-
dashcam track --name="TestDriver Tests" --type=application --pattern="*.log"
|
|
35
|
-
|
|
36
|
-
echo ""
|
|
37
|
-
|
|
38
|
-
# Run tests with Vitest and TestDriver reporter
|
|
39
|
-
echo "🧪 Running tests..."
|
|
40
|
-
npx vitest run --config vitest.config.example.js
|
|
41
|
-
|
|
42
|
-
# Capture exit code
|
|
43
|
-
TEST_EXIT_CODE=$?
|
|
44
|
-
|
|
45
|
-
# Stop dashcam
|
|
46
|
-
echo ""
|
|
47
|
-
echo "🛑 Stopping Dashcam..."
|
|
48
|
-
dashcam stop
|
|
49
|
-
|
|
50
|
-
# Publish to dashcam project if configured
|
|
51
|
-
if [ -n "$DASHCAM_PROJECT_ID" ]; then
|
|
52
|
-
echo "📤 Publishing replay to project: $DASHCAM_PROJECT_ID"
|
|
53
|
-
REPLAY_URL=$(dashcam publish -p "$DASHCAM_PROJECT_ID" --json | jq -r '.replayUrl')
|
|
54
|
-
echo "✅ Replay URL: $REPLAY_URL"
|
|
55
|
-
echo ""
|
|
56
|
-
echo "View your test recording at:"
|
|
57
|
-
echo "$REPLAY_URL"
|
|
58
|
-
else
|
|
59
|
-
echo "⚠️ Skipping publish (DASHCAM_PROJECT_ID not set)"
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
echo ""
|
|
63
|
-
echo "======================================"
|
|
64
|
-
echo "📊 View Results"
|
|
65
|
-
echo "======================================"
|
|
66
|
-
echo "Dashboard: https://app.testdriver.ai/dashboard/test-runs"
|
|
67
|
-
echo ""
|
|
68
|
-
|
|
69
|
-
# Exit with the same code as tests
|
|
70
|
-
exit $TEST_EXIT_CODE
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TestDriver SDK - Screenshot Example
|
|
3
|
-
*
|
|
4
|
-
* This example demonstrates how to use the screenshot() method
|
|
5
|
-
* to capture screenshots of the sandbox environment.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const TestDriver = require("../sdk.js");
|
|
9
|
-
const fs = require("fs");
|
|
10
|
-
const path = require("path");
|
|
11
|
-
|
|
12
|
-
async function main() {
|
|
13
|
-
// Initialize TestDriver SDK
|
|
14
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// Connect to sandbox
|
|
18
|
-
console.log("Connecting to sandbox...");
|
|
19
|
-
await client.connect();
|
|
20
|
-
|
|
21
|
-
// Navigate to a website
|
|
22
|
-
console.log("Opening Chrome and navigating to example.com...");
|
|
23
|
-
await client.focusApplication("Google Chrome");
|
|
24
|
-
const urlBar = await client.find("URL bar in Chrome");
|
|
25
|
-
await urlBar.click();
|
|
26
|
-
await client.type("https://example.com");
|
|
27
|
-
await client.pressKeys(["enter"]);
|
|
28
|
-
|
|
29
|
-
// Wait a moment for page to load
|
|
30
|
-
await client.wait(2000);
|
|
31
|
-
|
|
32
|
-
// Capture a screenshot
|
|
33
|
-
console.log("Capturing screenshot...");
|
|
34
|
-
const screenshot = await client.screenshot();
|
|
35
|
-
|
|
36
|
-
// Save screenshot to file
|
|
37
|
-
const outputPath = path.join(__dirname, "example-screenshot.png");
|
|
38
|
-
fs.writeFileSync(outputPath, Buffer.from(screenshot, "base64"));
|
|
39
|
-
console.log(`Screenshot saved to: ${outputPath}`);
|
|
40
|
-
|
|
41
|
-
// You can also capture with the mouse cursor visible
|
|
42
|
-
console.log("Capturing screenshot with mouse cursor...");
|
|
43
|
-
await client.hover(400, 300);
|
|
44
|
-
const screenshotWithMouse = await client.screenshot(1, false, true);
|
|
45
|
-
|
|
46
|
-
const outputPathWithMouse = path.join(
|
|
47
|
-
__dirname,
|
|
48
|
-
"example-screenshot-with-mouse.png",
|
|
49
|
-
);
|
|
50
|
-
fs.writeFileSync(
|
|
51
|
-
outputPathWithMouse,
|
|
52
|
-
Buffer.from(screenshotWithMouse, "base64"),
|
|
53
|
-
);
|
|
54
|
-
console.log(`Screenshot with mouse saved to: ${outputPathWithMouse}`);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error("Error:", error);
|
|
57
|
-
} finally {
|
|
58
|
-
// Clean up
|
|
59
|
-
await client.disconnect();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
main();
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TestDriver SDK - AWESOME Logs Demo 🎨
|
|
5
|
-
*
|
|
6
|
-
* This example showcases the beautiful, emoji-rich logging with great DX
|
|
7
|
-
* that makes your test output a joy to read!
|
|
8
|
-
*
|
|
9
|
-
* Run: TD_API_KEY=your_key node examples/sdk-awesome-logs-demo.js
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const TestDriver = require("../sdk.js");
|
|
13
|
-
const { formatter } = require("../sdk-log-formatter.js");
|
|
14
|
-
|
|
15
|
-
(async () => {
|
|
16
|
-
try {
|
|
17
|
-
console.log(
|
|
18
|
-
formatter.formatHeader("TestDriver SDK - AWESOME Logs Demo", "🚀"),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// Create client with logging enabled
|
|
22
|
-
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
23
|
-
os: "windows",
|
|
24
|
-
logging: true,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Demo 1: Connection
|
|
28
|
-
console.log(
|
|
29
|
-
formatter.formatConnection("connect", {
|
|
30
|
-
sandboxId: "demo-sandbox-123",
|
|
31
|
-
os: "Windows",
|
|
32
|
-
}),
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
await client.connect({ headless: true });
|
|
36
|
-
|
|
37
|
-
// Demo 2: Navigation
|
|
38
|
-
console.log(
|
|
39
|
-
"\n" + formatter.formatAction("navigate", "https://example.com"),
|
|
40
|
-
);
|
|
41
|
-
await client.focusApplication("Google Chrome");
|
|
42
|
-
await client.type("https://example.com");
|
|
43
|
-
await client.pressKeys(["enter"]);
|
|
44
|
-
|
|
45
|
-
// Demo 3: Wait with loading indicator
|
|
46
|
-
console.log("\n" + formatter.formatWaiting("for page to load", 2000));
|
|
47
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
48
|
-
|
|
49
|
-
// Demo 4: Finding elements (this will use the real formatElementFound from sdk.js)
|
|
50
|
-
console.log("\n" + formatter.formatHeader("Finding Elements", "🔍"));
|
|
51
|
-
|
|
52
|
-
const heading = await client.find("heading that says Example Domain");
|
|
53
|
-
// The actual find() call will emit the formatted log automatically
|
|
54
|
-
|
|
55
|
-
if (heading.found()) {
|
|
56
|
-
await heading.click();
|
|
57
|
-
// The click will also emit a formatted log automatically
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Demo 5: Multiple actions
|
|
61
|
-
console.log("\n" + formatter.formatHeader("User Actions", "👆"));
|
|
62
|
-
|
|
63
|
-
const link = await client.find("More information link");
|
|
64
|
-
if (link.found()) {
|
|
65
|
-
await link.hover();
|
|
66
|
-
await link.click();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Demo 6: Typing
|
|
70
|
-
console.log(
|
|
71
|
-
"\n" +
|
|
72
|
-
formatter.formatAction("type", "search query", {
|
|
73
|
-
text: "TestDriver AI",
|
|
74
|
-
}),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Demo 7: Scroll
|
|
78
|
-
console.log("\n" + formatter.formatAction("scroll", "down the page"));
|
|
79
|
-
await client.scroll("down", 300);
|
|
80
|
-
|
|
81
|
-
// Demo 8: Assertions
|
|
82
|
-
console.log("\n" + formatter.formatHeader("Assertions", "✅"));
|
|
83
|
-
console.log(
|
|
84
|
-
formatter.formatAssertion("Page title is correct", true, {
|
|
85
|
-
duration: "45ms",
|
|
86
|
-
}),
|
|
87
|
-
);
|
|
88
|
-
console.log(
|
|
89
|
-
formatter.formatAssertion("Footer is visible", true, {
|
|
90
|
-
duration: "23ms",
|
|
91
|
-
}),
|
|
92
|
-
);
|
|
93
|
-
console.log(
|
|
94
|
-
formatter.formatAssertion("Login button exists", false, {
|
|
95
|
-
duration: "1234ms",
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Demo 9: Cache status
|
|
100
|
-
console.log("\n" + formatter.formatHeader("Cache Performance", "⚡"));
|
|
101
|
-
console.log(
|
|
102
|
-
formatter.formatCacheStatus(true, {
|
|
103
|
-
similarity: 0.98,
|
|
104
|
-
strategy: "image",
|
|
105
|
-
}),
|
|
106
|
-
);
|
|
107
|
-
console.log(
|
|
108
|
-
formatter.formatCacheStatus(false, {
|
|
109
|
-
strategy: "text",
|
|
110
|
-
}),
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
// Demo 10: Screenshot
|
|
114
|
-
console.log(
|
|
115
|
-
"\n" +
|
|
116
|
-
formatter.formatScreenshot({
|
|
117
|
-
path: "/tmp/testdriver-debug/screenshot-123.png",
|
|
118
|
-
size: "245 KB",
|
|
119
|
-
}),
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Demo 11: Progress
|
|
123
|
-
console.log("\n" + formatter.formatHeader("Multi-step Process", "📈"));
|
|
124
|
-
for (let i = 1; i <= 5; i++) {
|
|
125
|
-
console.log(formatter.formatProgress(i, 5, `Processing step ${i}`));
|
|
126
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Demo 12: Divider
|
|
130
|
-
console.log("\n" + formatter.formatDivider());
|
|
131
|
-
|
|
132
|
-
// Demo 13: Test summary
|
|
133
|
-
console.log(
|
|
134
|
-
formatter.formatSummary({
|
|
135
|
-
passed: 12,
|
|
136
|
-
failed: 2,
|
|
137
|
-
skipped: 1,
|
|
138
|
-
total: 15,
|
|
139
|
-
duration: "45.23s",
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Demo 14: Error handling
|
|
144
|
-
console.log(formatter.formatHeader("Error Examples", "🚨"));
|
|
145
|
-
console.log(
|
|
146
|
-
formatter.formatError(
|
|
147
|
-
"Element not found",
|
|
148
|
-
new Error("Timeout after 5000ms"),
|
|
149
|
-
),
|
|
150
|
-
);
|
|
151
|
-
console.log(
|
|
152
|
-
formatter.formatError(
|
|
153
|
-
"Connection failed",
|
|
154
|
-
new Error("Network unreachable"),
|
|
155
|
-
),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
// Demo 15: Test lifecycle
|
|
159
|
-
console.log(formatter.formatTestStart("Login Flow Test"));
|
|
160
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
161
|
-
console.log(formatter.formatTestEnd("Login Flow Test", true, 2345));
|
|
162
|
-
|
|
163
|
-
console.log(formatter.formatTestStart("Checkout Process"));
|
|
164
|
-
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
165
|
-
console.log(formatter.formatTestEnd("Checkout Process", false, 5678));
|
|
166
|
-
|
|
167
|
-
// Final summary
|
|
168
|
-
console.log("\n" + formatter.formatHeader("Demo Complete!", "🎉"));
|
|
169
|
-
console.log("\n✨ Your test logs now look AWESOME! ✨\n");
|
|
170
|
-
|
|
171
|
-
await client.disconnect();
|
|
172
|
-
console.log("\n" + formatter.formatConnection("disconnect"));
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error(formatter.formatError("Demo failed", error));
|
|
175
|
-
process.exit(1);
|
|
176
|
-
}
|
|
177
|
-
})();
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TestDriver SDK - Cache Thresholds Example
|
|
5
|
-
*
|
|
6
|
-
* This example demonstrates how to configure cache thresholds for different
|
|
7
|
-
* operations and view cache debugging information.
|
|
8
|
-
*
|
|
9
|
-
* Run with VERBOSE=true to see cache hit/miss information:
|
|
10
|
-
* TD_API_KEY=your_key VERBOSE=true node examples/sdk-cache-thresholds.js
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const TestDriver = require("../sdk.js");
|
|
14
|
-
|
|
15
|
-
(async () => {
|
|
16
|
-
try {
|
|
17
|
-
// Create client with custom cache thresholds
|
|
18
|
-
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
19
|
-
os: "windows",
|
|
20
|
-
logging: true,
|
|
21
|
-
cacheThreshold: {
|
|
22
|
-
find: 0.03, // 3% difference = 97% similarity required for cache hit
|
|
23
|
-
findAll: 0.05, // 5% difference = 95% similarity required for cache hit
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
console.log("\n=== TestDriver SDK - Cache Thresholds Demo ===\n");
|
|
28
|
-
console.log("Cache thresholds configured:");
|
|
29
|
-
console.log(" - find: 0.03 (97% similarity required)");
|
|
30
|
-
console.log(" - findAll: 0.05 (95% similarity required)\n");
|
|
31
|
-
console.log("You can also override thresholds per-command:");
|
|
32
|
-
console.log(' await client.find("element", 0.01) // 99% similarity\n');
|
|
33
|
-
|
|
34
|
-
// Connect to sandbox
|
|
35
|
-
console.log("Connecting to sandbox...");
|
|
36
|
-
await client.connect({ headless: true });
|
|
37
|
-
|
|
38
|
-
// Open a test page
|
|
39
|
-
console.log("Opening test page...");
|
|
40
|
-
await client.focusApplication("Google Chrome");
|
|
41
|
-
await client.type("https://example.com");
|
|
42
|
-
await client.pressKeys(["enter"]);
|
|
43
|
-
|
|
44
|
-
// Wait for page load
|
|
45
|
-
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
46
|
-
|
|
47
|
-
// Example 1: First find - should be a cache MISS
|
|
48
|
-
console.log("\n--- First find (cache MISS expected) ---");
|
|
49
|
-
const heading1 = await client.find("heading that says Example Domain");
|
|
50
|
-
|
|
51
|
-
if (heading1.found()) {
|
|
52
|
-
console.log(`✓ Element found at (${heading1.x}, ${heading1.y})`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Example 2: Second find - should be a cache HIT (same element, same screen)
|
|
56
|
-
console.log("\n--- Second find (cache HIT expected) ---");
|
|
57
|
-
// eslint-disable-next-line no-unused-vars
|
|
58
|
-
const _heading2 = await client.find("heading that says Example Domain");
|
|
59
|
-
|
|
60
|
-
// Example 3: Find with custom threshold override
|
|
61
|
-
console.log("\n--- Find with strict threshold (0.01 = 99% similarity) ---");
|
|
62
|
-
// eslint-disable-next-line no-unused-vars
|
|
63
|
-
const _heading3 = await client.find(
|
|
64
|
-
"heading that says Example Domain",
|
|
65
|
-
0.01,
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// Example 4: Find a different element - cache MISS
|
|
69
|
-
console.log("\n--- Finding different element (cache MISS expected) ---");
|
|
70
|
-
// eslint-disable-next-line no-unused-vars
|
|
71
|
-
const _paragraph = await client.find(
|
|
72
|
-
"paragraph with text about illustrative examples",
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
// Example 5: Find the same paragraph again - cache HIT
|
|
76
|
-
console.log("\n--- Finding same paragraph again (cache HIT expected) ---");
|
|
77
|
-
// eslint-disable-next-line no-unused-vars
|
|
78
|
-
const _paragraph2 = await client.find(
|
|
79
|
-
"paragraph with text about illustrative examples",
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
console.log("\n=== Demo Complete ===");
|
|
83
|
-
console.log(
|
|
84
|
-
"\nNote: Run with VERBOSE=true to see detailed cache information:",
|
|
85
|
-
);
|
|
86
|
-
console.log(" - Cache hit/miss status");
|
|
87
|
-
console.log(" - Cache strategy (image/text)");
|
|
88
|
-
console.log(" - Similarity scores");
|
|
89
|
-
console.log(" - Response times\n");
|
|
90
|
-
|
|
91
|
-
await client.disconnect();
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error("Test failed:", error);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
})();
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TestDriver SDK - Element Properties Example
|
|
5
|
-
*
|
|
6
|
-
* This example demonstrates accessing all available properties from located elements,
|
|
7
|
-
* including coordinates, dimensions, confidence scores, screenshots, and more.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const TestDriverSDK = require("../sdk");
|
|
11
|
-
|
|
12
|
-
(async () => {
|
|
13
|
-
const client = new TestDriverSDK(process.env.TD_API_KEY);
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
await client.connect();
|
|
17
|
-
|
|
18
|
-
// Example 1: Basic coordinate properties
|
|
19
|
-
console.log("=== Example 1: Basic Coordinates ===");
|
|
20
|
-
const button = await client.find("the login button");
|
|
21
|
-
|
|
22
|
-
if (button.found()) {
|
|
23
|
-
console.log("Button found!");
|
|
24
|
-
console.log(" X (top-left):", button.x);
|
|
25
|
-
console.log(" Y (top-left):", button.y);
|
|
26
|
-
console.log(" Center X:", button.centerX);
|
|
27
|
-
console.log(" Center Y:", button.centerY);
|
|
28
|
-
console.log(" Coordinates object:", button.getCoordinates());
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Example 2: Element dimensions
|
|
32
|
-
console.log("\n=== Example 2: Element Dimensions ===");
|
|
33
|
-
const input = await client.find("username input field");
|
|
34
|
-
|
|
35
|
-
if (input.found()) {
|
|
36
|
-
console.log("Input field found!");
|
|
37
|
-
console.log(" Width:", input.width);
|
|
38
|
-
console.log(" Height:", input.height);
|
|
39
|
-
|
|
40
|
-
if (input.boundingBox) {
|
|
41
|
-
console.log(" Bounding box:", input.boundingBox);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Example 3: Confidence and text data
|
|
46
|
-
console.log("\n=== Example 3: Match Quality & Text ===");
|
|
47
|
-
const link = await client.find("sign up link");
|
|
48
|
-
|
|
49
|
-
if (link.found()) {
|
|
50
|
-
console.log("Link found!");
|
|
51
|
-
console.log(" Confidence score:", link.confidence);
|
|
52
|
-
console.log(" Text content:", link.text);
|
|
53
|
-
console.log(" Label:", link.label);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Example 4: Screenshot data
|
|
57
|
-
console.log("\n=== Example 4: Element Screenshot ===");
|
|
58
|
-
const icon = await client.find("settings icon");
|
|
59
|
-
|
|
60
|
-
if (icon.found() && icon.screenshot) {
|
|
61
|
-
console.log("Icon found with screenshot!");
|
|
62
|
-
console.log(" Screenshot (base64) length:", icon.screenshot.length);
|
|
63
|
-
|
|
64
|
-
// You could save this to a file:
|
|
65
|
-
// const fs = require('fs');
|
|
66
|
-
// fs.writeFileSync('element.png', Buffer.from(icon.screenshot, 'base64'));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Example 5: Full API response
|
|
70
|
-
console.log("\n=== Example 5: Full API Response ===");
|
|
71
|
-
const widget = await client.find("main content area");
|
|
72
|
-
|
|
73
|
-
if (widget.found()) {
|
|
74
|
-
const fullResponse = widget.getResponse();
|
|
75
|
-
console.log("Full API response:", JSON.stringify(fullResponse, null, 2));
|
|
76
|
-
|
|
77
|
-
// Log all available properties
|
|
78
|
-
if (fullResponse) {
|
|
79
|
-
console.log("\nAll available properties:");
|
|
80
|
-
Object.keys(fullResponse).forEach((key) => {
|
|
81
|
-
const value = fullResponse[key];
|
|
82
|
-
const preview =
|
|
83
|
-
typeof value === "string" && value.length > 50
|
|
84
|
-
? value.substring(0, 50) + "..."
|
|
85
|
-
: value;
|
|
86
|
-
console.log(` ${key}:`, preview);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Example 6: Property-based validation
|
|
92
|
-
console.log("\n=== Example 6: Property-based Validation ===");
|
|
93
|
-
const message = await client.find("error message");
|
|
94
|
-
|
|
95
|
-
if (message.found()) {
|
|
96
|
-
// Check position
|
|
97
|
-
if (message.centerY < 200) {
|
|
98
|
-
console.log("✓ Error message is at top of screen");
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Check confidence
|
|
102
|
-
if (message.confidence && message.confidence > 0.9) {
|
|
103
|
-
console.log("✓ High confidence match (", message.confidence, ")");
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Check text content
|
|
107
|
-
if (message.text) {
|
|
108
|
-
console.log("✓ Message text:", message.text);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Example 7: Position-based logic
|
|
113
|
-
console.log("\n=== Example 7: Position-based Logic ===");
|
|
114
|
-
const menu = await client.find("dropdown menu");
|
|
115
|
-
|
|
116
|
-
if (menu.found()) {
|
|
117
|
-
// Calculate positions
|
|
118
|
-
const offsetX = menu.x + 10;
|
|
119
|
-
const offsetY = menu.y + 20;
|
|
120
|
-
console.log("Menu position:", { x: menu.x, y: menu.y });
|
|
121
|
-
console.log("Offset position:", { x: offsetX, y: offsetY });
|
|
122
|
-
|
|
123
|
-
// Check if element is in viewport
|
|
124
|
-
const viewportHeight = 768;
|
|
125
|
-
if (menu.y > 0 && menu.y < viewportHeight) {
|
|
126
|
-
console.log("✓ Element is visible in viewport");
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Example 8: Conditional actions based on properties
|
|
131
|
-
console.log("\n=== Example 8: Conditional Actions ===");
|
|
132
|
-
const notification = await client.find("notification popup");
|
|
133
|
-
|
|
134
|
-
if (notification.found()) {
|
|
135
|
-
// Only interact if confidence is high
|
|
136
|
-
if (notification.confidence && notification.confidence > 0.8) {
|
|
137
|
-
console.log("High confidence, clicking notification");
|
|
138
|
-
await notification.click();
|
|
139
|
-
} else {
|
|
140
|
-
console.log("Low confidence, skipping interaction");
|
|
141
|
-
console.log("Debug info:", {
|
|
142
|
-
coordinates: notification.getCoordinates(),
|
|
143
|
-
confidence: notification.confidence,
|
|
144
|
-
text: notification.text,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
await client.disconnect();
|
|
150
|
-
} catch (error) {
|
|
151
|
-
console.error("Test failed:", error);
|
|
152
|
-
await client.disconnect();
|
|
153
|
-
process.exit(1);
|
|
154
|
-
}
|
|
155
|
-
})();
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TestDriver SDK - Simple Example with AWESOME Logs 🎨
|
|
5
|
-
*
|
|
6
|
-
* A straightforward example showing the beautiful logging in action.
|
|
7
|
-
*
|
|
8
|
-
* Run: TD_API_KEY=your_key node examples/sdk-simple-example.js
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const TestDriver = require("../sdk.js");
|
|
12
|
-
|
|
13
|
-
(async () => {
|
|
14
|
-
try {
|
|
15
|
-
// Create client with logging enabled (default)
|
|
16
|
-
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
17
|
-
os: "windows",
|
|
18
|
-
logging: true, // This enables the awesome logs!
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
console.log("\n🚀 Starting TestDriver SDK Example...\n");
|
|
22
|
-
|
|
23
|
-
// Connect to sandbox - you'll see: 🔌 Connected
|
|
24
|
-
await client.connect({ headless: true });
|
|
25
|
-
|
|
26
|
-
// Navigate to a test page
|
|
27
|
-
await client.focusApplication("Google Chrome");
|
|
28
|
-
await client.type("https://example.com");
|
|
29
|
-
await client.pressKeys(["enter"]);
|
|
30
|
-
|
|
31
|
-
// Wait for page load
|
|
32
|
-
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
33
|
-
|
|
34
|
-
// Find an element - you'll see: 🔍 Found "heading..." · 📍 (x, y) · ⏱️ XXXms · ⚡ cached
|
|
35
|
-
const heading = await client.find("heading that says Example Domain");
|
|
36
|
-
|
|
37
|
-
if (heading.found()) {
|
|
38
|
-
// Click the element - you'll see: 👆 Click "heading..."
|
|
39
|
-
await heading.click();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Find another element
|
|
43
|
-
const link = await client.find("More information link");
|
|
44
|
-
|
|
45
|
-
if (link.found()) {
|
|
46
|
-
// Hover over it - you'll see: 👉 Hover "More information link"
|
|
47
|
-
await link.hover();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Scroll down - you'll see: 📜 Scroll
|
|
51
|
-
await client.scroll("down", 300);
|
|
52
|
-
|
|
53
|
-
// Take a screenshot - you'll see: 📸 Screenshot
|
|
54
|
-
const screenshot = await client.screenshot();
|
|
55
|
-
console.log(`\n📸 Screenshot captured (${screenshot.length} bytes)\n`);
|
|
56
|
-
|
|
57
|
-
// Disconnect - you'll see: 🔌 Disconnected
|
|
58
|
-
await client.disconnect();
|
|
59
|
-
|
|
60
|
-
console.log("\n✅ Example completed successfully!\n");
|
|
61
|
-
} catch (error) {
|
|
62
|
-
console.error(`\n❌ Error: ${error.message}\n`);
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
})();
|