@testdriverai/mcp 7.9.115-test → 7.9.117-test
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/agent/index.js +38 -17
- package/ai/skills/testdriver-ci-cd/SKILL.md +58 -1
- package/ai/skills/testdriver:ci-cd/SKILL.md +58 -1
- package/docs/_data/examples-manifest.json +46 -46
- package/docs/v7/ci-cd.mdx +58 -1
- package/docs/v7/examples/ai.mdx +1 -1
- package/docs/v7/examples/assert.mdx +1 -1
- package/docs/v7/examples/chrome-extension.mdx +1 -1
- package/docs/v7/examples/element-not-found.mdx +1 -1
- package/docs/v7/examples/findall-coffee-icons.mdx +1 -1
- package/docs/v7/examples/hover-image.mdx +1 -1
- package/docs/v7/examples/hover-text-with-description.mdx +1 -1
- package/docs/v7/examples/hover-text.mdx +1 -1
- package/docs/v7/examples/installer.mdx +1 -1
- package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
- package/docs/v7/examples/parse.mdx +1 -1
- package/docs/v7/examples/press-keys.mdx +1 -1
- package/docs/v7/examples/scroll-keyboard.mdx +1 -1
- package/docs/v7/examples/scroll.mdx +1 -1
- package/docs/v7/examples/type.mdx +1 -1
- package/mcp-server/dist/core/actions.d.ts +176 -0
- package/mcp-server/dist/core/actions.js +753 -0
- package/mcp-server/dist/server.mjs +283 -781
- package/mcp-server/package.json +1 -0
- package/mcp-server/src/core/actions.ts +912 -0
- package/mcp-server/src/server.ts +329 -988
- package/package.json +13 -1
package/agent/index.js
CHANGED
|
@@ -1992,29 +1992,50 @@ ${regression}
|
|
|
1992
1992
|
// Write session file for IDE preview (VSCode extension watches for these)
|
|
1993
1993
|
writeIdeSessionFile(debuggerUrl, data) {
|
|
1994
1994
|
const fs = require("fs");
|
|
1995
|
+
const os = require("os");
|
|
1995
1996
|
const path = require("path");
|
|
1996
1997
|
|
|
1997
|
-
|
|
1998
|
-
|
|
1998
|
+
// Base dir for the preview file. `process.cwd()` is read-only in some hosts
|
|
1999
|
+
// (e.g. Vercel/Lambda serverless, where cwd is /var/task), which makes the
|
|
2000
|
+
// mkdir below throw. Allow an explicit override and otherwise fall back to a
|
|
2001
|
+
// writable temp dir, so a preview write never blocks the session.
|
|
2002
|
+
const baseDir =
|
|
2003
|
+
process.env.TD_PREVIEWS_DIR ||
|
|
2004
|
+
(this.config && this.config.TD_PREVIEWS_DIR) ||
|
|
2005
|
+
process.cwd();
|
|
2006
|
+
const previewsDir = path.join(baseDir, ".testdriver", ".previews");
|
|
1999
2007
|
|
|
2000
|
-
|
|
2001
|
-
if (!fs.existsSync(previewsDir)) {
|
|
2002
|
-
fs.mkdirSync(previewsDir, { recursive: true });
|
|
2003
|
-
}
|
|
2008
|
+
const sessionId = `${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
2004
2009
|
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2010
|
+
// The IDE preview file is a best-effort convenience (the VSCode extension
|
|
2011
|
+
// watches for it). It must never break session start — if the target dir
|
|
2012
|
+
// isn't writable, fall back to os.tmpdir(), and if that also fails, log and
|
|
2013
|
+
// move on rather than throwing out of the provisioning path.
|
|
2014
|
+
try {
|
|
2015
|
+
const sessionData = {
|
|
2016
|
+
sessionId,
|
|
2017
|
+
debuggerUrl,
|
|
2018
|
+
resolution: Array.isArray(data.resolution) ? data.resolution : (data.resolution ? data.resolution.split("x").map(Number) : [1920, 1080]),
|
|
2019
|
+
testFile: data.testFile || this.testFile || null,
|
|
2020
|
+
os: data.os || this.sandboxOs || "linux",
|
|
2021
|
+
timestamp: Date.now(),
|
|
2022
|
+
};
|
|
2013
2023
|
|
|
2014
|
-
|
|
2015
|
-
|
|
2024
|
+
let dir = previewsDir;
|
|
2025
|
+
try {
|
|
2026
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
2027
|
+
} catch {
|
|
2028
|
+
// cwd/base wasn't writable — retry under the OS temp dir.
|
|
2029
|
+
dir = path.join(os.tmpdir(), ".testdriver", ".previews");
|
|
2030
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2031
|
+
}
|
|
2016
2032
|
|
|
2017
|
-
|
|
2033
|
+
const filePath = path.join(dir, `${sessionId}.json`);
|
|
2034
|
+
fs.writeFileSync(filePath, JSON.stringify(sessionData, null, 2));
|
|
2035
|
+
logger.log(`IDE preview session written to ${filePath}`);
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
logger.log(`Skipped IDE preview session file (non-fatal): ${error.message}`);
|
|
2038
|
+
}
|
|
2018
2039
|
}
|
|
2019
2040
|
|
|
2020
2041
|
// Find the VS Code instance that contains the test file
|
|
@@ -27,8 +27,65 @@ TestDriver requires an API key to authenticate with the TestDriver cloud. Store
|
|
|
27
27
|
|
|
28
28
|
<Tabs>
|
|
29
29
|
<Tab title="GitHub Actions">
|
|
30
|
+
### Authenticate with OIDC (recommended)
|
|
31
|
+
|
|
32
|
+
If you've installed the [TestDriver GitHub App](https://console.testdriver.ai), your workflow can authenticate using GitHub's OIDC token — no long-lived `TD_API_KEY` secret to store or rotate. The workflow proves it's running inside your org, and TestDriver exchanges that proof for your team's API key at run time.
|
|
33
|
+
|
|
34
|
+
<Note>
|
|
35
|
+
This requires the TestDriver GitHub App to be authorized for your organization once (from the [console](https://console.testdriver.ai)). If your org authorized the App before OIDC support shipped, re-run the authorization once so the binding is created.
|
|
36
|
+
</Note>
|
|
37
|
+
|
|
38
|
+
Grant the job the `id-token: write` permission and exchange the OIDC token for your API key:
|
|
39
|
+
|
|
40
|
+
```yaml .github/workflows/testdriver.yml
|
|
41
|
+
name: TestDriver Tests
|
|
42
|
+
|
|
43
|
+
on:
|
|
44
|
+
push:
|
|
45
|
+
branches: [main]
|
|
46
|
+
pull_request:
|
|
47
|
+
branches: [main]
|
|
48
|
+
|
|
49
|
+
jobs:
|
|
50
|
+
test:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
permissions:
|
|
53
|
+
id-token: write # required to mint an OIDC token
|
|
54
|
+
contents: read
|
|
55
|
+
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
- uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: '20'
|
|
62
|
+
cache: 'npm'
|
|
63
|
+
|
|
64
|
+
- run: npm ci
|
|
65
|
+
|
|
66
|
+
- name: Authenticate to TestDriver via OIDC
|
|
67
|
+
run: |
|
|
68
|
+
OIDC_TOKEN=$(curl -sS \
|
|
69
|
+
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
70
|
+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=testdriver" | jq -r '.value')
|
|
71
|
+
API_KEY=$(curl -sS -X POST https://api.testdriver.ai/github/actions/auth \
|
|
72
|
+
-H "Content-Type: application/json" \
|
|
73
|
+
-d "{\"token\":\"$OIDC_TOKEN\"}" | jq -r '.apiKey')
|
|
74
|
+
echo "::add-mask::$API_KEY"
|
|
75
|
+
echo "TD_API_KEY=$API_KEY" >> "$GITHUB_ENV"
|
|
76
|
+
|
|
77
|
+
- name: Run TestDriver tests
|
|
78
|
+
env:
|
|
79
|
+
TD_API_KEY: ${{ env.TD_API_KEY }}
|
|
80
|
+
run: vitest --run
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`ACTIONS_ID_TOKEN_REQUEST_TOKEN` and `ACTIONS_ID_TOKEN_REQUEST_URL` are injected automatically once `permissions: id-token: write` is set. `::add-mask::` keeps the resolved key out of the logs.
|
|
84
|
+
|
|
30
85
|
### Adding Secrets
|
|
31
|
-
|
|
86
|
+
|
|
87
|
+
Prefer OIDC above when possible. If you can't use the GitHub App (e.g. self-hosted runners without OIDC, or a non-GitHub registry), fall back to a stored API key:
|
|
88
|
+
|
|
32
89
|
1. Navigate to your GitHub repository
|
|
33
90
|
2. Go to **Settings** → **Secrets and variables** → **Actions**
|
|
34
91
|
3. Click **New repository secret**
|
|
@@ -27,8 +27,65 @@ TestDriver requires an API key to authenticate with the TestDriver cloud. Store
|
|
|
27
27
|
|
|
28
28
|
<Tabs>
|
|
29
29
|
<Tab title="GitHub Actions">
|
|
30
|
+
### Authenticate with OIDC (recommended)
|
|
31
|
+
|
|
32
|
+
If you've installed the [TestDriver GitHub App](https://console.testdriver.ai), your workflow can authenticate using GitHub's OIDC token — no long-lived `TD_API_KEY` secret to store or rotate. The workflow proves it's running inside your org, and TestDriver exchanges that proof for your team's API key at run time.
|
|
33
|
+
|
|
34
|
+
<Note>
|
|
35
|
+
This requires the TestDriver GitHub App to be authorized for your organization once (from the [console](https://console.testdriver.ai)). If your org authorized the App before OIDC support shipped, re-run the authorization once so the binding is created.
|
|
36
|
+
</Note>
|
|
37
|
+
|
|
38
|
+
Grant the job the `id-token: write` permission and exchange the OIDC token for your API key:
|
|
39
|
+
|
|
40
|
+
```yaml .github/workflows/testdriver.yml
|
|
41
|
+
name: TestDriver Tests
|
|
42
|
+
|
|
43
|
+
on:
|
|
44
|
+
push:
|
|
45
|
+
branches: [main]
|
|
46
|
+
pull_request:
|
|
47
|
+
branches: [main]
|
|
48
|
+
|
|
49
|
+
jobs:
|
|
50
|
+
test:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
permissions:
|
|
53
|
+
id-token: write # required to mint an OIDC token
|
|
54
|
+
contents: read
|
|
55
|
+
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
- uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: '20'
|
|
62
|
+
cache: 'npm'
|
|
63
|
+
|
|
64
|
+
- run: npm ci
|
|
65
|
+
|
|
66
|
+
- name: Authenticate to TestDriver via OIDC
|
|
67
|
+
run: |
|
|
68
|
+
OIDC_TOKEN=$(curl -sS \
|
|
69
|
+
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
70
|
+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=testdriver" | jq -r '.value')
|
|
71
|
+
API_KEY=$(curl -sS -X POST https://api.testdriver.ai/github/actions/auth \
|
|
72
|
+
-H "Content-Type: application/json" \
|
|
73
|
+
-d "{\"token\":\"$OIDC_TOKEN\"}" | jq -r '.apiKey')
|
|
74
|
+
echo "::add-mask::$API_KEY"
|
|
75
|
+
echo "TD_API_KEY=$API_KEY" >> "$GITHUB_ENV"
|
|
76
|
+
|
|
77
|
+
- name: Run TestDriver tests
|
|
78
|
+
env:
|
|
79
|
+
TD_API_KEY: ${{ env.TD_API_KEY }}
|
|
80
|
+
run: vitest --run
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`ACTIONS_ID_TOKEN_REQUEST_TOKEN` and `ACTIONS_ID_TOKEN_REQUEST_URL` are injected automatically once `permissions: id-token: write` is set. `::add-mask::` keeps the resolved key out of the logs.
|
|
84
|
+
|
|
30
85
|
### Adding Secrets
|
|
31
|
-
|
|
86
|
+
|
|
87
|
+
Prefer OIDC above when possible. If you can't use the GitHub App (e.g. self-hosted runners without OIDC, or a non-GitHub registry), fall back to a stored API key:
|
|
88
|
+
|
|
32
89
|
1. Navigate to your GitHub repository
|
|
33
90
|
2. Go to **Settings** → **Secrets and variables** → **Actions**
|
|
34
91
|
3. Click **New repository secret**
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"$schema": "./examples-manifest.schema.json",
|
|
3
3
|
"examples": {
|
|
4
4
|
"assert.test.mjs": {
|
|
5
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
6
|
-
"lastUpdated": "2026-06-
|
|
5
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7ca663fcb03ae03d95fe",
|
|
6
|
+
"lastUpdated": "2026-06-25T00:56:06.006Z"
|
|
7
7
|
},
|
|
8
8
|
"drag-and-drop.test.mjs": {
|
|
9
9
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62b42fc0ac3cc632a918b",
|
|
10
10
|
"lastUpdated": "2026-03-03T00:32:25.275Z"
|
|
11
11
|
},
|
|
12
12
|
"exec-pwsh.test.mjs": {
|
|
13
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
14
|
-
"lastUpdated": "2026-06-
|
|
13
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7bbc63fcb03ae03d95e8",
|
|
14
|
+
"lastUpdated": "2026-06-25T00:59:30.997Z"
|
|
15
15
|
},
|
|
16
16
|
"match-image.test.mjs": {
|
|
17
17
|
"url": "https://console-test.testdriver.ai/runs/69c8738614b73310c7839412/69c8738c14b73310c783941d",
|
|
@@ -22,88 +22,88 @@
|
|
|
22
22
|
"lastUpdated": "2026-03-03T00:32:25.282Z"
|
|
23
23
|
},
|
|
24
24
|
"hover-text-with-description.test.mjs": {
|
|
25
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
26
|
-
"lastUpdated": "2026-06-
|
|
25
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7bd363fcb03ae03d95e9",
|
|
26
|
+
"lastUpdated": "2026-06-25T00:59:53.824Z"
|
|
27
27
|
},
|
|
28
28
|
"windows-installer.test.mjs": {
|
|
29
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
30
|
-
"lastUpdated": "2026-06-
|
|
29
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c0463fcb03ae03d95f4",
|
|
30
|
+
"lastUpdated": "2026-06-25T01:18:30.616Z"
|
|
31
31
|
},
|
|
32
32
|
"exec-output.test.mjs": {
|
|
33
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
34
|
-
"lastUpdated": "2026-06-
|
|
33
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c0663fcb03ae03d95f5",
|
|
34
|
+
"lastUpdated": "2026-06-25T01:07:35.289Z"
|
|
35
35
|
},
|
|
36
36
|
"chrome-extension.test.mjs": {
|
|
37
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
38
|
-
"lastUpdated": "2026-06-
|
|
37
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7bba63fcb03ae03d95e7",
|
|
38
|
+
"lastUpdated": "2026-06-25T00:59:28.703Z"
|
|
39
39
|
},
|
|
40
40
|
"launch-vscode-linux.test.mjs": {
|
|
41
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
42
|
-
"lastUpdated": "2026-06-
|
|
41
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c0263fcb03ae03d95f2",
|
|
42
|
+
"lastUpdated": "2026-06-25T01:07:32.243Z"
|
|
43
43
|
},
|
|
44
44
|
"hover-image.test.mjs": {
|
|
45
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
46
|
-
"lastUpdated": "2026-06-
|
|
45
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c1f63fcb03ae03d95f6",
|
|
46
|
+
"lastUpdated": "2026-06-25T00:53:50.924Z"
|
|
47
47
|
},
|
|
48
48
|
"installer.test.mjs": {
|
|
49
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
50
|
-
"lastUpdated": "2026-06-
|
|
49
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c4963fcb03ae03d95f8",
|
|
50
|
+
"lastUpdated": "2026-06-25T00:54:33.314Z"
|
|
51
51
|
},
|
|
52
52
|
"type.test.mjs": {
|
|
53
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
54
|
-
"lastUpdated": "2026-06-
|
|
53
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c7763fcb03ae03d95fc",
|
|
54
|
+
"lastUpdated": "2026-06-25T01:09:29.100Z"
|
|
55
55
|
},
|
|
56
56
|
"press-keys.test.mjs": {
|
|
57
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
58
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
59
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
60
|
-
"lastUpdated": "2026-06-
|
|
57
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7c8e63fcb03ae03d95fd",
|
|
58
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a3c835ca377db15ec79a1bd?share=FaNdmOecF7rCwJK30fmZ2g",
|
|
59
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a3c835ca377db15ec79a1bd?share=FaNdmOecF7rCwJK30fmZ2g&embed=true",
|
|
60
|
+
"lastUpdated": "2026-06-25T01:24:50.989Z"
|
|
61
61
|
},
|
|
62
62
|
"scroll-keyboard.test.mjs": {
|
|
63
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
64
|
-
"lastUpdated": "2026-06-
|
|
63
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cd563fcb03ae03d9600",
|
|
64
|
+
"lastUpdated": "2026-06-25T01:10:59.352Z"
|
|
65
65
|
},
|
|
66
66
|
"scroll.test.mjs": {
|
|
67
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
68
|
-
"lastUpdated": "2026-06-
|
|
67
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cf463fcb03ae03d9604",
|
|
68
|
+
"lastUpdated": "2026-06-25T01:04:32.288Z"
|
|
69
69
|
},
|
|
70
70
|
"scroll-until-image.test.mjs": {
|
|
71
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
72
|
-
"lastUpdated": "2026-06-
|
|
71
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cd763fcb03ae03d9601",
|
|
72
|
+
"lastUpdated": "2026-06-25T00:56:55.949Z"
|
|
73
73
|
},
|
|
74
74
|
"prompt.test.mjs": {
|
|
75
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
76
|
-
"lastUpdated": "2026-06-
|
|
75
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cd963fcb03ae03d9602",
|
|
76
|
+
"lastUpdated": "2026-06-25T01:11:02.429Z"
|
|
77
77
|
},
|
|
78
78
|
"focus-window.test.mjs": {
|
|
79
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
80
|
-
"lastUpdated": "2026-06-
|
|
79
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cdb63fcb03ae03d9603",
|
|
80
|
+
"lastUpdated": "2026-06-25T01:11:03.876Z"
|
|
81
81
|
},
|
|
82
82
|
"captcha-api.test.mjs": {
|
|
83
83
|
"url": "https://console.testdriver.ai/runs/698f7df69e27ce1528d7d087/698f7fb0d3b320ad547d9d44",
|
|
84
84
|
"lastUpdated": "2026-02-13T19:55:05.951Z"
|
|
85
85
|
},
|
|
86
86
|
"element-not-found.test.mjs": {
|
|
87
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
88
|
-
"lastUpdated": "2026-06-
|
|
87
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7d0b63fcb03ae03d9605",
|
|
88
|
+
"lastUpdated": "2026-06-25T01:04:52.990Z"
|
|
89
89
|
},
|
|
90
90
|
"formatted-logging.test.mjs": {
|
|
91
91
|
"url": "https://console-test.testdriver.ai/runs/69c8738614b73310c7839412/69c873a714b73310c7839450",
|
|
92
92
|
"lastUpdated": "2026-03-29T00:36:10.628Z"
|
|
93
93
|
},
|
|
94
94
|
"hover-text.test.mjs": {
|
|
95
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
96
|
-
"lastUpdated": "2026-06-
|
|
95
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7d3b63fcb03ae03d9607",
|
|
96
|
+
"lastUpdated": "2026-06-25T01:05:38.141Z"
|
|
97
97
|
},
|
|
98
98
|
"no-provision.test.mjs": {
|
|
99
99
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62b7706a177a05bccd1cf",
|
|
100
100
|
"lastUpdated": "2026-03-03T00:32:25.279Z"
|
|
101
101
|
},
|
|
102
102
|
"ai.test.mjs": {
|
|
103
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
104
|
-
"replayUrl": "https://console-test.testdriver.ai/replay/
|
|
105
|
-
"embedUrl": "https://console-test.testdriver.ai/replay/
|
|
106
|
-
"lastUpdated": "2026-06-
|
|
103
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7d2263fcb03ae03d9606",
|
|
104
|
+
"replayUrl": "https://console-test.testdriver.ai/replay/6a3c85bda377db15ec79a1cb?share=atuShrmwV3Td5vfB5wOXTw",
|
|
105
|
+
"embedUrl": "https://console-test.testdriver.ai/replay/6a3c85bda377db15ec79a1cb?share=atuShrmwV3Td5vfB5wOXTw&embed=true",
|
|
106
|
+
"lastUpdated": "2026-06-25T01:34:59.921Z"
|
|
107
107
|
},
|
|
108
108
|
"popup-loading.test.mjs": {
|
|
109
109
|
"url": "https://console.testdriver.ai/runs/698bc89f7140c3fa7daaca8d/698bca7f7140c3fa7daacbf7",
|
|
@@ -138,12 +138,12 @@
|
|
|
138
138
|
"lastUpdated": "2026-02-13T19:55:05.953Z"
|
|
139
139
|
},
|
|
140
140
|
"findall-coffee-icons.test.mjs": {
|
|
141
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
142
|
-
"lastUpdated": "2026-06-
|
|
141
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7cbe63fcb03ae03d95ff",
|
|
142
|
+
"lastUpdated": "2026-06-25T00:56:30.004Z"
|
|
143
143
|
},
|
|
144
144
|
"parse.test.mjs": {
|
|
145
|
-
"url": "https://console-test.testdriver.ai/runs/
|
|
146
|
-
"lastUpdated": "2026-06-
|
|
145
|
+
"url": "https://console-test.testdriver.ai/runs/6a3c7ba263fcb03ae03d95e4/6a3c7d5363fcb03ae03d9609",
|
|
146
|
+
"lastUpdated": "2026-06-25T01:06:00.212Z"
|
|
147
147
|
},
|
|
148
148
|
"flake-diffthreshold-001.test.mjs": {
|
|
149
149
|
"url": "https://console.testdriver.ai/runs/69a62b3aaa712ecd3dea730a/69a62bcafc0ac3cc632a91aa",
|
package/docs/v7/ci-cd.mdx
CHANGED
|
@@ -28,8 +28,65 @@ TestDriver requires an API key to authenticate with the TestDriver cloud. Store
|
|
|
28
28
|
|
|
29
29
|
<Tabs>
|
|
30
30
|
<Tab title="GitHub Actions">
|
|
31
|
+
### Authenticate with OIDC (recommended)
|
|
32
|
+
|
|
33
|
+
If you've installed the [TestDriver GitHub App](https://console.testdriver.ai), your workflow can authenticate using GitHub's OIDC token — no long-lived `TD_API_KEY` secret to store or rotate. The workflow proves it's running inside your org, and TestDriver exchanges that proof for your team's API key at run time.
|
|
34
|
+
|
|
35
|
+
<Note>
|
|
36
|
+
This requires the TestDriver GitHub App to be authorized for your organization once (from the [console](https://console.testdriver.ai)). If your org authorized the App before OIDC support shipped, re-run the authorization once so the binding is created.
|
|
37
|
+
</Note>
|
|
38
|
+
|
|
39
|
+
Grant the job the `id-token: write` permission and exchange the OIDC token for your API key:
|
|
40
|
+
|
|
41
|
+
```yaml .github/workflows/testdriver.yml
|
|
42
|
+
name: TestDriver Tests
|
|
43
|
+
|
|
44
|
+
on:
|
|
45
|
+
push:
|
|
46
|
+
branches: [main]
|
|
47
|
+
pull_request:
|
|
48
|
+
branches: [main]
|
|
49
|
+
|
|
50
|
+
jobs:
|
|
51
|
+
test:
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
permissions:
|
|
54
|
+
id-token: write # required to mint an OIDC token
|
|
55
|
+
contents: read
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
|
|
60
|
+
- uses: actions/setup-node@v4
|
|
61
|
+
with:
|
|
62
|
+
node-version: '20'
|
|
63
|
+
cache: 'npm'
|
|
64
|
+
|
|
65
|
+
- run: npm ci
|
|
66
|
+
|
|
67
|
+
- name: Authenticate to TestDriver via OIDC
|
|
68
|
+
run: |
|
|
69
|
+
OIDC_TOKEN=$(curl -sS \
|
|
70
|
+
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
71
|
+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=testdriver" | jq -r '.value')
|
|
72
|
+
API_KEY=$(curl -sS -X POST https://api.testdriver.ai/github/actions/auth \
|
|
73
|
+
-H "Content-Type: application/json" \
|
|
74
|
+
-d "{\"token\":\"$OIDC_TOKEN\"}" | jq -r '.apiKey')
|
|
75
|
+
echo "::add-mask::$API_KEY"
|
|
76
|
+
echo "TD_API_KEY=$API_KEY" >> "$GITHUB_ENV"
|
|
77
|
+
|
|
78
|
+
- name: Run TestDriver tests
|
|
79
|
+
env:
|
|
80
|
+
TD_API_KEY: ${{ env.TD_API_KEY }}
|
|
81
|
+
run: vitest --run
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`ACTIONS_ID_TOKEN_REQUEST_TOKEN` and `ACTIONS_ID_TOKEN_REQUEST_URL` are injected automatically once `permissions: id-token: write` is set. `::add-mask::` keeps the resolved key out of the logs.
|
|
85
|
+
|
|
31
86
|
### Adding Secrets
|
|
32
|
-
|
|
87
|
+
|
|
88
|
+
Prefer OIDC above when possible. If you can't use the GitHub App (e.g. self-hosted runners without OIDC, or a non-GitHub registry), fall back to a stored API key:
|
|
89
|
+
|
|
33
90
|
1. Navigate to your GitHub repository
|
|
34
91
|
2. Go to **Settings** → **Secrets and variables** → **Actions**
|
|
35
92
|
3. Click **New repository secret**
|
package/docs/v7/examples/ai.mdx
CHANGED
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* ai.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a3c85bda377db15ec79a1cb?share=atuShrmwV3Td5vfB5wOXTw&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* assert.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7ca663fcb03ae03d95fe/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* chrome-extension.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7bba63fcb03ae03d95e7/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* element-not-found.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7d0b63fcb03ae03d9605/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* findall-coffee-icons.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7cbe63fcb03ae03d95ff/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* hover-image.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7c1f63fcb03ae03d95f6/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* hover-text-with-description.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7bd363fcb03ae03d95e9/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* hover-text.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7d3b63fcb03ae03d9607/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* installer.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7c4963fcb03ae03d95f8/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* launch-vscode-linux.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7c0263fcb03ae03d95f2/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -18,7 +18,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
18
18
|
|
|
19
19
|
{/* parse.test.mjs output */}
|
|
20
20
|
<iframe
|
|
21
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
21
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7d5363fcb03ae03d9609/replay"
|
|
22
22
|
width="100%"
|
|
23
23
|
height="600"
|
|
24
24
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* press-keys.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://console-test.testdriver.ai/replay/
|
|
15
|
+
src="https://console-test.testdriver.ai/replay/6a3c835ca377db15ec79a1bd?share=FaNdmOecF7rCwJK30fmZ2g&embed=true"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* scroll-keyboard.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7cd563fcb03ae03d9600/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* scroll.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7cf463fcb03ae03d9604/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|
|
@@ -12,7 +12,7 @@ Watch this test execute in a real sandbox environment:
|
|
|
12
12
|
|
|
13
13
|
{/* type.test.mjs output */}
|
|
14
14
|
<iframe
|
|
15
|
-
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/
|
|
15
|
+
src="https://api-test.testdriver.ai/api/v1/testdriver/testcase/6a3c7c7763fcb03ae03d95fc/replay"
|
|
16
16
|
width="100%"
|
|
17
17
|
height="390"
|
|
18
18
|
style={{ border: "1px solid #333", borderRadius: "8px" }}
|