testdriverai 7.1.4 → 7.2.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/.github/workflows/acceptance.yaml +81 -0
- package/.github/workflows/publish.yaml +44 -0
- package/agent/index.js +18 -19
- 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 +69 -42
- package/lib/core/Dashcam.js +65 -66
- package/lib/vitest/hooks.mjs +42 -50
- package/package.json +1 -1
- package/sdk-log-formatter.js +350 -175
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Acceptance Tests
|
|
2
|
+
permissions:
|
|
3
|
+
id-token: write
|
|
4
|
+
contents: write
|
|
5
|
+
pull-requests: write
|
|
6
|
+
checks: write
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [ main ]
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test-linux:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup Node.js
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: '20'
|
|
26
|
+
cache: 'npm'
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: npm ci
|
|
30
|
+
|
|
31
|
+
- name: Run Linux tests
|
|
32
|
+
run: npx vitest run test/testdriver/*.test.mjs
|
|
33
|
+
env:
|
|
34
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
35
|
+
TD_OS: linux
|
|
36
|
+
|
|
37
|
+
- name: Upload test results to Sentry Prevent
|
|
38
|
+
if: ${{ !cancelled() }}
|
|
39
|
+
uses: getsentry/prevent-action@v0
|
|
40
|
+
|
|
41
|
+
- name: Publish Test Results
|
|
42
|
+
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
43
|
+
if: always()
|
|
44
|
+
with:
|
|
45
|
+
files: test-report.junit.xml
|
|
46
|
+
comment_mode: always
|
|
47
|
+
check_name: Test Results (Linux)
|
|
48
|
+
|
|
49
|
+
test-windows:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
if: contains(github.event.pull_request.labels.*.name, 'test-windows')
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Setup Node.js
|
|
57
|
+
uses: actions/setup-node@v4
|
|
58
|
+
with:
|
|
59
|
+
node-version: '20'
|
|
60
|
+
cache: 'npm'
|
|
61
|
+
|
|
62
|
+
- name: Install dependencies
|
|
63
|
+
run: npm ci
|
|
64
|
+
|
|
65
|
+
- name: Run Windows tests
|
|
66
|
+
run: npx vitest run test/testdriver/*.test.mjs
|
|
67
|
+
env:
|
|
68
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
69
|
+
TD_OS: windows
|
|
70
|
+
|
|
71
|
+
- name: Upload test results to Sentry Prevent
|
|
72
|
+
if: ${{ !cancelled() }}
|
|
73
|
+
uses: getsentry/prevent-action@v0
|
|
74
|
+
|
|
75
|
+
- name: Publish Test Results
|
|
76
|
+
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
77
|
+
if: always()
|
|
78
|
+
with:
|
|
79
|
+
files: test-report.junit.xml
|
|
80
|
+
comment_mode: always
|
|
81
|
+
check_name: Test Results (Windows)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Publish Beta
|
|
2
|
+
permissions:
|
|
3
|
+
contents: write
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [ main ]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish-beta:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
17
|
+
|
|
18
|
+
- name: Setup Node.js
|
|
19
|
+
uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: '20'
|
|
22
|
+
registry-url: 'https://registry.npmjs.org/'
|
|
23
|
+
|
|
24
|
+
- name: Configure Git
|
|
25
|
+
run: |
|
|
26
|
+
git config user.name "github-actions[bot]"
|
|
27
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: npm ci
|
|
31
|
+
|
|
32
|
+
- name: Bump version (prerelease beta)
|
|
33
|
+
run: npm version prerelease --preid=beta --no-git-tag-version
|
|
34
|
+
|
|
35
|
+
- name: Commit and push version bump
|
|
36
|
+
run: |
|
|
37
|
+
git add package.json package-lock.json
|
|
38
|
+
git commit -m "chore: bump beta version to $(node -p "require('./package.json').version")"
|
|
39
|
+
git push
|
|
40
|
+
|
|
41
|
+
- name: Publish to npm under beta tag
|
|
42
|
+
run: npm publish --tag beta
|
|
43
|
+
env:
|
|
44
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/agent/index.js
CHANGED
|
@@ -183,7 +183,8 @@ class TestDriverAgent extends EventEmitter2 {
|
|
|
183
183
|
// single function to handle all program exits
|
|
184
184
|
// allows us to save the current state, run lifecycle hooks, and track analytics
|
|
185
185
|
async exit(failed = true, shouldSave = false, shouldRunPostrun = false) {
|
|
186
|
-
|
|
186
|
+
const { formatter } = require("../sdk-log-formatter.js");
|
|
187
|
+
this.emitter.emit(events.log.narration, formatter.getPrefix("disconnect") + " " + theme.yellow.bold("Exiting") + theme.dim("..."), true);
|
|
187
188
|
|
|
188
189
|
// Clean up redraw interval
|
|
189
190
|
if (this.redraw && this.redraw.cleanup) {
|
|
@@ -1838,6 +1839,9 @@ ${regression}
|
|
|
1838
1839
|
}
|
|
1839
1840
|
}
|
|
1840
1841
|
|
|
1842
|
+
// Create session first so session ID is available for Sentry tracing in WebSocket connection
|
|
1843
|
+
await this.newSession();
|
|
1844
|
+
|
|
1841
1845
|
// order is important!
|
|
1842
1846
|
await this.connectToSandboxService();
|
|
1843
1847
|
|
|
@@ -1856,7 +1860,6 @@ ${regression}
|
|
|
1856
1860
|
|
|
1857
1861
|
this.instance = instance.instance;
|
|
1858
1862
|
await this.renderSandbox(this.instance, headless);
|
|
1859
|
-
await this.newSession();
|
|
1860
1863
|
await this.runLifecycle("provision");
|
|
1861
1864
|
|
|
1862
1865
|
return;
|
|
@@ -1877,7 +1880,6 @@ ${regression}
|
|
|
1877
1880
|
this.instance = instance;
|
|
1878
1881
|
|
|
1879
1882
|
await this.renderSandbox(instance, headless);
|
|
1880
|
-
await this.newSession();
|
|
1881
1883
|
return;
|
|
1882
1884
|
} catch (error) {
|
|
1883
1885
|
// If connection fails, fall through to creating a new sandbox
|
|
@@ -1909,7 +1911,6 @@ ${regression}
|
|
|
1909
1911
|
this.instance = instance;
|
|
1910
1912
|
|
|
1911
1913
|
await this.renderSandbox(instance, headless);
|
|
1912
|
-
await this.newSession();
|
|
1913
1914
|
return;
|
|
1914
1915
|
} catch (error) {
|
|
1915
1916
|
// If connection fails, fall through to creating a new sandbox
|
|
@@ -1923,9 +1924,10 @@ ${regression}
|
|
|
1923
1924
|
|
|
1924
1925
|
// Create new sandbox (either because createNew is true, or no existing sandbox to connect to)
|
|
1925
1926
|
if (!this.instance) {
|
|
1927
|
+
const { formatter } = require("../sdk-log-formatter.js");
|
|
1926
1928
|
this.emitter.emit(
|
|
1927
1929
|
events.log.narration,
|
|
1928
|
-
theme.
|
|
1930
|
+
formatter.getPrefix("connect") + " " + theme.green.bold("Creating") + " " + theme.cyan(`new sandbox...`),
|
|
1929
1931
|
);
|
|
1930
1932
|
// We don't have resiliency/retries baked in, so let's at least give it 1 attempt
|
|
1931
1933
|
// to see if that fixes the issue.
|
|
@@ -1949,10 +1951,7 @@ ${regression}
|
|
|
1949
1951
|
);
|
|
1950
1952
|
this.instance = instance;
|
|
1951
1953
|
await this.renderSandbox(instance, headless);
|
|
1952
|
-
await this.newSession();
|
|
1953
1954
|
await this.runLifecycle("provision");
|
|
1954
|
-
|
|
1955
|
-
console.log("provision run");
|
|
1956
1955
|
}
|
|
1957
1956
|
}
|
|
1958
1957
|
|
|
@@ -2073,7 +2072,6 @@ ${regression}
|
|
|
2073
2072
|
}
|
|
2074
2073
|
|
|
2075
2074
|
async renderSandbox(instance, headless = false) {
|
|
2076
|
-
console.log("renderSandbox", instance);
|
|
2077
2075
|
|
|
2078
2076
|
if (!headless) {
|
|
2079
2077
|
let url;
|
|
@@ -2126,7 +2124,8 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2126
2124
|
);
|
|
2127
2125
|
}
|
|
2128
2126
|
|
|
2129
|
-
|
|
2127
|
+
const { formatter } = require("../sdk-log-formatter.js");
|
|
2128
|
+
this.emitter.emit(events.log.narration, formatter.getPrefix("connect") + " " + theme.green.bold("Authenticating") + theme.dim("..."));
|
|
2130
2129
|
let ableToAuth = await this.sandbox.auth(this.config.TD_API_KEY);
|
|
2131
2130
|
|
|
2132
2131
|
if (!ableToAuth) {
|
|
@@ -2139,7 +2138,8 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2139
2138
|
}
|
|
2140
2139
|
|
|
2141
2140
|
async connectToSandboxDirect(sandboxId, persist = false) {
|
|
2142
|
-
|
|
2141
|
+
const { formatter } = require("../sdk-log-formatter.js");
|
|
2142
|
+
this.emitter.emit(events.log.narration, formatter.getPrefix("connect") + " " + theme.green.bold("Connecting") + " " + theme.cyan(`to sandbox...`));
|
|
2143
2143
|
let reply = await this.sandbox.connect(sandboxId, persist);
|
|
2144
2144
|
|
|
2145
2145
|
// reply includes { success, url, sandbox: {...} }
|
|
@@ -2170,7 +2170,7 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2170
2170
|
sandboxConfig.instanceType = this.sandboxInstance;
|
|
2171
2171
|
}
|
|
2172
2172
|
|
|
2173
|
-
let instance = await this.sandbox.send(sandboxConfig);
|
|
2173
|
+
let instance = await this.sandbox.send(sandboxConfig, 60000 * 8);
|
|
2174
2174
|
|
|
2175
2175
|
// Save the sandbox ID for reconnection with the correct OS type
|
|
2176
2176
|
if (instance.sandbox && instance.sandbox.sandboxId) {
|
|
@@ -2184,10 +2184,13 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2184
2184
|
|
|
2185
2185
|
async newSession() {
|
|
2186
2186
|
// should be start of new session
|
|
2187
|
+
// If sandbox is connected, get system info; otherwise pass empty objects
|
|
2188
|
+
const isSandboxConnected = this.sandbox.apiSocketConnected;
|
|
2189
|
+
|
|
2187
2190
|
const sessionRes = await this.sdk.req("session/start", {
|
|
2188
|
-
systemInformationOsInfo: await this.system.getSystemInformationOsInfo(),
|
|
2189
|
-
mousePosition: await this.system.getMousePosition(),
|
|
2190
|
-
activeWindow: await this.system.activeWin(),
|
|
2191
|
+
systemInformationOsInfo: isSandboxConnected ? await this.system.getSystemInformationOsInfo() : {},
|
|
2192
|
+
mousePosition: isSandboxConnected ? await this.system.getMousePosition() : {},
|
|
2193
|
+
activeWindow: isSandboxConnected ? await this.system.activeWin() : {},
|
|
2191
2194
|
});
|
|
2192
2195
|
|
|
2193
2196
|
if (!sessionRes) {
|
|
@@ -2265,9 +2268,6 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2265
2268
|
// If sourceMapper doesn't have a current file, use thisFile which should be the file being run
|
|
2266
2269
|
let currentFilePath = this.sourceMapper.currentFilePath || this.thisFile;
|
|
2267
2270
|
|
|
2268
|
-
this.emitter.emit(events.log.log, ``);
|
|
2269
|
-
this.emitter.emit(events.log.log, "Running lifecycle: " + lifecycleName);
|
|
2270
|
-
|
|
2271
2271
|
// If we still don't have a currentFilePath, fall back to the default testdriver directory
|
|
2272
2272
|
if (!currentFilePath) {
|
|
2273
2273
|
currentFilePath = path.join(
|
|
@@ -2275,7 +2275,6 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2275
2275
|
"testdriver",
|
|
2276
2276
|
"testdriver.yaml",
|
|
2277
2277
|
);
|
|
2278
|
-
console.log("No currentFilePath found, using fallback:", currentFilePath);
|
|
2279
2278
|
}
|
|
2280
2279
|
|
|
2281
2280
|
// Ensure we have an absolute path
|