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
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Azure Pipelines"
|
|
3
|
+
description: "Run TestDriver tests in Azure Pipelines"
|
|
4
|
+
icon: "microsoft"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Basic Setup
|
|
8
|
+
|
|
9
|
+
Create `azure-pipelines.yml`:
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
trigger:
|
|
13
|
+
- main
|
|
14
|
+
- develop
|
|
15
|
+
|
|
16
|
+
pool:
|
|
17
|
+
vmImage: 'ubuntu-latest'
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- task: NodeTool@0
|
|
21
|
+
inputs:
|
|
22
|
+
versionSpec: '18.x'
|
|
23
|
+
displayName: 'Install Node.js'
|
|
24
|
+
|
|
25
|
+
- script: npm ci
|
|
26
|
+
displayName: 'Install dependencies'
|
|
27
|
+
|
|
28
|
+
- script: npx vitest
|
|
29
|
+
displayName: 'Run tests'
|
|
30
|
+
env:
|
|
31
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
32
|
+
|
|
33
|
+
- task: PublishTestResults@2
|
|
34
|
+
condition: always()
|
|
35
|
+
inputs:
|
|
36
|
+
testResultsFiles: 'test-results/junit.xml'
|
|
37
|
+
testRunTitle: 'TestDriver Tests'
|
|
38
|
+
|
|
39
|
+
- task: PublishBuildArtifacts@1
|
|
40
|
+
condition: always()
|
|
41
|
+
inputs:
|
|
42
|
+
pathToPublish: 'test-results'
|
|
43
|
+
artifactName: 'test-results'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Add API Key
|
|
47
|
+
|
|
48
|
+
### Using Variable Groups
|
|
49
|
+
|
|
50
|
+
1. Go to **Pipelines** → **Library**
|
|
51
|
+
2. Click **+ Variable group**
|
|
52
|
+
3. Name: `testdriver-vars`
|
|
53
|
+
4. Click **+ Add**
|
|
54
|
+
5. Name: `TD_API_KEY`
|
|
55
|
+
6. Value: Your API key from [dashboard.testdriver.ai](https://dashboard.testdriver.ai)
|
|
56
|
+
7. Click the lock icon to make it secret
|
|
57
|
+
8. Click **Save**
|
|
58
|
+
|
|
59
|
+
Reference in pipeline:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
variables:
|
|
63
|
+
- group: testdriver-vars
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- script: npx vitest
|
|
67
|
+
env:
|
|
68
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Using Pipeline Variables
|
|
72
|
+
|
|
73
|
+
Or set directly in pipeline:
|
|
74
|
+
|
|
75
|
+
1. Edit pipeline in Azure DevOps
|
|
76
|
+
2. Click **Variables** button
|
|
77
|
+
3. Click **New variable**
|
|
78
|
+
4. Name: `TD_API_KEY`
|
|
79
|
+
5. Value: Your API key
|
|
80
|
+
6. Check **Keep this value secret**
|
|
81
|
+
7. Click **OK** and **Save**
|
|
82
|
+
|
|
83
|
+
## Parallel Jobs
|
|
84
|
+
|
|
85
|
+
Run tests in parallel:
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
trigger:
|
|
89
|
+
- main
|
|
90
|
+
|
|
91
|
+
strategy:
|
|
92
|
+
matrix:
|
|
93
|
+
shard1:
|
|
94
|
+
shardIndex: 1
|
|
95
|
+
shard2:
|
|
96
|
+
shardIndex: 2
|
|
97
|
+
shard3:
|
|
98
|
+
shardIndex: 3
|
|
99
|
+
shard4:
|
|
100
|
+
shardIndex: 4
|
|
101
|
+
maxParallel: 4
|
|
102
|
+
|
|
103
|
+
pool:
|
|
104
|
+
vmImage: 'ubuntu-latest'
|
|
105
|
+
|
|
106
|
+
variables:
|
|
107
|
+
- group: testdriver-vars
|
|
108
|
+
|
|
109
|
+
steps:
|
|
110
|
+
- task: NodeTool@0
|
|
111
|
+
inputs:
|
|
112
|
+
versionSpec: '18.x'
|
|
113
|
+
|
|
114
|
+
- script: npm ci
|
|
115
|
+
displayName: 'Install dependencies'
|
|
116
|
+
|
|
117
|
+
- script: npx vitest --shard=$(shardIndex)/4
|
|
118
|
+
displayName: 'Run tests (shard $(shardIndex)/4)'
|
|
119
|
+
env:
|
|
120
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
121
|
+
|
|
122
|
+
- task: PublishTestResults@2
|
|
123
|
+
condition: always()
|
|
124
|
+
inputs:
|
|
125
|
+
testResultsFiles: 'test-results/junit.xml'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Save Dashcam URLs
|
|
129
|
+
|
|
130
|
+
Extract replay URLs from test output:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
steps:
|
|
134
|
+
- script: |
|
|
135
|
+
npx vitest 2>&1 | tee test-output.log
|
|
136
|
+
grep -o 'https://dashcam.testdriver.ai/[a-zA-Z0-9-]*' test-output.log > dashcam-urls.txt || true
|
|
137
|
+
displayName: 'Run tests and extract Dashcam URLs'
|
|
138
|
+
env:
|
|
139
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
140
|
+
|
|
141
|
+
- task: PublishBuildArtifacts@1
|
|
142
|
+
condition: always()
|
|
143
|
+
inputs:
|
|
144
|
+
pathToPublish: 'test-output.log'
|
|
145
|
+
artifactName: 'logs'
|
|
146
|
+
|
|
147
|
+
- task: PublishBuildArtifacts@1
|
|
148
|
+
condition: always()
|
|
149
|
+
inputs:
|
|
150
|
+
pathToPublish: 'dashcam-urls.txt'
|
|
151
|
+
artifactName: 'dashcam-urls'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Scheduled Builds
|
|
155
|
+
|
|
156
|
+
Run tests on schedule:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
trigger: none # Disable CI triggers
|
|
160
|
+
|
|
161
|
+
schedules:
|
|
162
|
+
- cron: "0 2 * * *" # 2 AM daily
|
|
163
|
+
displayName: Nightly tests
|
|
164
|
+
branches:
|
|
165
|
+
include:
|
|
166
|
+
- main
|
|
167
|
+
always: true # Run even if no code changes
|
|
168
|
+
|
|
169
|
+
pool:
|
|
170
|
+
vmImage: 'ubuntu-latest'
|
|
171
|
+
|
|
172
|
+
variables:
|
|
173
|
+
- group: testdriver-vars
|
|
174
|
+
|
|
175
|
+
steps:
|
|
176
|
+
- task: NodeTool@0
|
|
177
|
+
inputs:
|
|
178
|
+
versionSpec: '18.x'
|
|
179
|
+
|
|
180
|
+
- script: npm ci
|
|
181
|
+
displayName: 'Install dependencies'
|
|
182
|
+
|
|
183
|
+
- script: npx vitest
|
|
184
|
+
displayName: 'Run tests'
|
|
185
|
+
env:
|
|
186
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Multiple Node Versions
|
|
190
|
+
|
|
191
|
+
Test across Node.js versions:
|
|
192
|
+
|
|
193
|
+
```yaml
|
|
194
|
+
trigger:
|
|
195
|
+
- main
|
|
196
|
+
|
|
197
|
+
strategy:
|
|
198
|
+
matrix:
|
|
199
|
+
node16:
|
|
200
|
+
nodeVersion: '16.x'
|
|
201
|
+
node18:
|
|
202
|
+
nodeVersion: '18.x'
|
|
203
|
+
node20:
|
|
204
|
+
nodeVersion: '20.x'
|
|
205
|
+
|
|
206
|
+
pool:
|
|
207
|
+
vmImage: 'ubuntu-latest'
|
|
208
|
+
|
|
209
|
+
variables:
|
|
210
|
+
- group: testdriver-vars
|
|
211
|
+
|
|
212
|
+
steps:
|
|
213
|
+
- task: NodeTool@0
|
|
214
|
+
inputs:
|
|
215
|
+
versionSpec: $(nodeVersion)
|
|
216
|
+
displayName: 'Install Node.js $(nodeVersion)'
|
|
217
|
+
|
|
218
|
+
- script: npm ci
|
|
219
|
+
displayName: 'Install dependencies'
|
|
220
|
+
|
|
221
|
+
- script: npx vitest
|
|
222
|
+
displayName: 'Run tests'
|
|
223
|
+
env:
|
|
224
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Conditional Execution
|
|
228
|
+
|
|
229
|
+
Skip tests on documentation changes:
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
trigger:
|
|
233
|
+
branches:
|
|
234
|
+
include:
|
|
235
|
+
- main
|
|
236
|
+
- develop
|
|
237
|
+
paths:
|
|
238
|
+
exclude:
|
|
239
|
+
- '*.md'
|
|
240
|
+
- 'docs/**'
|
|
241
|
+
|
|
242
|
+
steps:
|
|
243
|
+
- script: npx vitest
|
|
244
|
+
env:
|
|
245
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Or use conditions:
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
steps:
|
|
252
|
+
- script: |
|
|
253
|
+
if git diff --name-only HEAD~1 | grep -qE '^(src|test)/'; then
|
|
254
|
+
echo "##vso[task.setvariable variable=RUN_TESTS]true"
|
|
255
|
+
else
|
|
256
|
+
echo "Only docs changed"
|
|
257
|
+
echo "##vso[task.setvariable variable=RUN_TESTS]false"
|
|
258
|
+
fi
|
|
259
|
+
displayName: 'Check for code changes'
|
|
260
|
+
|
|
261
|
+
- script: npx vitest
|
|
262
|
+
condition: eq(variables.RUN_TESTS, 'true')
|
|
263
|
+
displayName: 'Run tests'
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Cache Dependencies
|
|
267
|
+
|
|
268
|
+
Speed up builds with caching:
|
|
269
|
+
|
|
270
|
+
```yaml
|
|
271
|
+
steps:
|
|
272
|
+
- task: Cache@2
|
|
273
|
+
inputs:
|
|
274
|
+
key: 'npm | "$(Agent.OS)" | package-lock.json'
|
|
275
|
+
path: '$(npm_config_cache)'
|
|
276
|
+
restoreKeys: |
|
|
277
|
+
npm | "$(Agent.OS)"
|
|
278
|
+
displayName: 'Cache npm'
|
|
279
|
+
|
|
280
|
+
- script: npm ci
|
|
281
|
+
displayName: 'Install dependencies'
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Templates
|
|
285
|
+
|
|
286
|
+
Reuse pipeline logic with templates:
|
|
287
|
+
|
|
288
|
+
Create `templates/test-template.yml`:
|
|
289
|
+
|
|
290
|
+
```yaml
|
|
291
|
+
parameters:
|
|
292
|
+
- name: nodeVersion
|
|
293
|
+
type: string
|
|
294
|
+
default: '18.x'
|
|
295
|
+
|
|
296
|
+
steps:
|
|
297
|
+
- task: NodeTool@0
|
|
298
|
+
inputs:
|
|
299
|
+
versionSpec: ${{ parameters.nodeVersion }}
|
|
300
|
+
|
|
301
|
+
- script: npm ci
|
|
302
|
+
displayName: 'Install dependencies'
|
|
303
|
+
|
|
304
|
+
- script: npx vitest
|
|
305
|
+
displayName: 'Run tests'
|
|
306
|
+
env:
|
|
307
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
308
|
+
|
|
309
|
+
- task: PublishTestResults@2
|
|
310
|
+
condition: always()
|
|
311
|
+
inputs:
|
|
312
|
+
testResultsFiles: 'test-results/junit.xml'
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Use in `azure-pipelines.yml`:
|
|
316
|
+
|
|
317
|
+
```yaml
|
|
318
|
+
variables:
|
|
319
|
+
- group: testdriver-vars
|
|
320
|
+
|
|
321
|
+
jobs:
|
|
322
|
+
- job: test_node16
|
|
323
|
+
pool:
|
|
324
|
+
vmImage: 'ubuntu-latest'
|
|
325
|
+
steps:
|
|
326
|
+
- template: templates/test-template.yml
|
|
327
|
+
parameters:
|
|
328
|
+
nodeVersion: '16.x'
|
|
329
|
+
|
|
330
|
+
- job: test_node18
|
|
331
|
+
pool:
|
|
332
|
+
vmImage: 'ubuntu-latest'
|
|
333
|
+
steps:
|
|
334
|
+
- template: templates/test-template.yml
|
|
335
|
+
parameters:
|
|
336
|
+
nodeVersion: '18.x'
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Multi-Stage Pipeline
|
|
340
|
+
|
|
341
|
+
Separate build and test stages:
|
|
342
|
+
|
|
343
|
+
```yaml
|
|
344
|
+
trigger:
|
|
345
|
+
- main
|
|
346
|
+
|
|
347
|
+
variables:
|
|
348
|
+
- group: testdriver-vars
|
|
349
|
+
|
|
350
|
+
stages:
|
|
351
|
+
- stage: Build
|
|
352
|
+
jobs:
|
|
353
|
+
- job: install
|
|
354
|
+
pool:
|
|
355
|
+
vmImage: 'ubuntu-latest'
|
|
356
|
+
steps:
|
|
357
|
+
- task: NodeTool@0
|
|
358
|
+
inputs:
|
|
359
|
+
versionSpec: '18.x'
|
|
360
|
+
|
|
361
|
+
- script: npm ci
|
|
362
|
+
displayName: 'Install dependencies'
|
|
363
|
+
|
|
364
|
+
- task: PublishPipelineArtifact@1
|
|
365
|
+
inputs:
|
|
366
|
+
targetPath: 'node_modules'
|
|
367
|
+
artifactName: 'node_modules'
|
|
368
|
+
|
|
369
|
+
- stage: Test
|
|
370
|
+
dependsOn: Build
|
|
371
|
+
jobs:
|
|
372
|
+
- job: test
|
|
373
|
+
pool:
|
|
374
|
+
vmImage: 'ubuntu-latest'
|
|
375
|
+
steps:
|
|
376
|
+
- task: NodeTool@0
|
|
377
|
+
inputs:
|
|
378
|
+
versionSpec: '18.x'
|
|
379
|
+
|
|
380
|
+
- task: DownloadPipelineArtifact@2
|
|
381
|
+
inputs:
|
|
382
|
+
artifactName: 'node_modules'
|
|
383
|
+
targetPath: 'node_modules'
|
|
384
|
+
|
|
385
|
+
- script: npx vitest
|
|
386
|
+
displayName: 'Run tests'
|
|
387
|
+
env:
|
|
388
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Approval Gates
|
|
392
|
+
|
|
393
|
+
Add manual approval:
|
|
394
|
+
|
|
395
|
+
```yaml
|
|
396
|
+
stages:
|
|
397
|
+
- stage: Test
|
|
398
|
+
jobs:
|
|
399
|
+
- job: test
|
|
400
|
+
pool:
|
|
401
|
+
vmImage: 'ubuntu-latest'
|
|
402
|
+
steps:
|
|
403
|
+
- script: npx vitest
|
|
404
|
+
|
|
405
|
+
- stage: Deploy
|
|
406
|
+
dependsOn: Test
|
|
407
|
+
jobs:
|
|
408
|
+
- deployment: deploy
|
|
409
|
+
environment: 'production' # Requires approval in Environments
|
|
410
|
+
strategy:
|
|
411
|
+
runOnce:
|
|
412
|
+
deploy:
|
|
413
|
+
steps:
|
|
414
|
+
- script: echo "Deploying..."
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Configure approval in **Pipelines** → **Environments** → **production** → **Approvals and checks**.
|
|
418
|
+
|
|
419
|
+
## Notifications
|
|
420
|
+
|
|
421
|
+
Send notifications on failure:
|
|
422
|
+
|
|
423
|
+
```yaml
|
|
424
|
+
steps:
|
|
425
|
+
- script: npx vitest
|
|
426
|
+
displayName: 'Run tests'
|
|
427
|
+
env:
|
|
428
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
429
|
+
|
|
430
|
+
- task: SendEmail@1
|
|
431
|
+
condition: failed()
|
|
432
|
+
inputs:
|
|
433
|
+
to: 'team@example.com'
|
|
434
|
+
subject: 'Pipeline Failed: $(Build.DefinitionName)'
|
|
435
|
+
body: |
|
|
436
|
+
Build $(Build.BuildNumber) failed.
|
|
437
|
+
|
|
438
|
+
View build: $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Troubleshooting
|
|
442
|
+
|
|
443
|
+
### Tests timeout
|
|
444
|
+
|
|
445
|
+
Increase timeout:
|
|
446
|
+
|
|
447
|
+
```yaml
|
|
448
|
+
steps:
|
|
449
|
+
- script: npx vitest
|
|
450
|
+
displayName: 'Run tests'
|
|
451
|
+
timeoutInMinutes: 30 # Default is 60
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### API key not found
|
|
455
|
+
|
|
456
|
+
Debug variables:
|
|
457
|
+
|
|
458
|
+
```yaml
|
|
459
|
+
steps:
|
|
460
|
+
- script: |
|
|
461
|
+
echo "Has TD_API_KEY: ${TD_API_KEY:+yes}"
|
|
462
|
+
node --version
|
|
463
|
+
env:
|
|
464
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Out of parallel jobs
|
|
468
|
+
|
|
469
|
+
Check your Azure DevOps plan limits. Free tier includes:
|
|
470
|
+
- 1 parallel job for private repos
|
|
471
|
+
- 10 parallel jobs for public repos
|
|
472
|
+
|
|
473
|
+
## Complete Example
|
|
474
|
+
|
|
475
|
+
Full-featured pipeline:
|
|
476
|
+
|
|
477
|
+
```yaml
|
|
478
|
+
trigger:
|
|
479
|
+
branches:
|
|
480
|
+
include:
|
|
481
|
+
- main
|
|
482
|
+
- develop
|
|
483
|
+
paths:
|
|
484
|
+
exclude:
|
|
485
|
+
- '*.md'
|
|
486
|
+
- 'docs/**'
|
|
487
|
+
|
|
488
|
+
pr:
|
|
489
|
+
branches:
|
|
490
|
+
include:
|
|
491
|
+
- main
|
|
492
|
+
- develop
|
|
493
|
+
|
|
494
|
+
schedules:
|
|
495
|
+
- cron: "0 2 * * *"
|
|
496
|
+
displayName: Nightly tests
|
|
497
|
+
branches:
|
|
498
|
+
include:
|
|
499
|
+
- main
|
|
500
|
+
always: true
|
|
501
|
+
|
|
502
|
+
variables:
|
|
503
|
+
- group: testdriver-vars
|
|
504
|
+
|
|
505
|
+
pool:
|
|
506
|
+
vmImage: 'ubuntu-latest'
|
|
507
|
+
|
|
508
|
+
strategy:
|
|
509
|
+
matrix:
|
|
510
|
+
shard1:
|
|
511
|
+
shardIndex: 1
|
|
512
|
+
shard2:
|
|
513
|
+
shardIndex: 2
|
|
514
|
+
shard3:
|
|
515
|
+
shardIndex: 3
|
|
516
|
+
shard4:
|
|
517
|
+
shardIndex: 4
|
|
518
|
+
maxParallel: 4
|
|
519
|
+
|
|
520
|
+
steps:
|
|
521
|
+
- task: NodeTool@0
|
|
522
|
+
inputs:
|
|
523
|
+
versionSpec: '18.x'
|
|
524
|
+
displayName: 'Install Node.js'
|
|
525
|
+
|
|
526
|
+
- task: Cache@2
|
|
527
|
+
inputs:
|
|
528
|
+
key: 'npm | "$(Agent.OS)" | package-lock.json'
|
|
529
|
+
path: '$(npm_config_cache)'
|
|
530
|
+
displayName: 'Cache npm'
|
|
531
|
+
|
|
532
|
+
- script: npm ci
|
|
533
|
+
displayName: 'Install dependencies'
|
|
534
|
+
|
|
535
|
+
- script: |
|
|
536
|
+
npx vitest --shard=$(shardIndex)/4 2>&1 | tee test-output-$(shardIndex).log
|
|
537
|
+
grep -o 'https://dashcam.testdriver.ai/[a-zA-Z0-9-]*' test-output-$(shardIndex).log > dashcam-urls-$(shardIndex).txt || true
|
|
538
|
+
displayName: 'Run tests (shard $(shardIndex)/4)'
|
|
539
|
+
env:
|
|
540
|
+
TD_API_KEY: $(TD_API_KEY)
|
|
541
|
+
timeoutInMinutes: 30
|
|
542
|
+
|
|
543
|
+
- task: PublishTestResults@2
|
|
544
|
+
condition: always()
|
|
545
|
+
inputs:
|
|
546
|
+
testResultsFiles: 'test-results/junit.xml'
|
|
547
|
+
testRunTitle: 'TestDriver Tests (Shard $(shardIndex))'
|
|
548
|
+
mergeTestResults: true
|
|
549
|
+
|
|
550
|
+
- task: PublishBuildArtifacts@1
|
|
551
|
+
condition: always()
|
|
552
|
+
inputs:
|
|
553
|
+
pathToPublish: 'test-results'
|
|
554
|
+
artifactName: 'test-results-$(shardIndex)'
|
|
555
|
+
|
|
556
|
+
- task: PublishBuildArtifacts@1
|
|
557
|
+
condition: always()
|
|
558
|
+
inputs:
|
|
559
|
+
pathToPublish: 'test-output-$(shardIndex).log'
|
|
560
|
+
artifactName: 'logs-$(shardIndex)'
|
|
561
|
+
|
|
562
|
+
- task: PublishBuildArtifacts@1
|
|
563
|
+
condition: always()
|
|
564
|
+
inputs:
|
|
565
|
+
pathToPublish: 'dashcam-urls-$(shardIndex).txt'
|
|
566
|
+
artifactName: 'dashcam-urls-$(shardIndex)'
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## See Also
|
|
570
|
+
|
|
571
|
+
<CardGroup cols={2}>
|
|
572
|
+
<Card title="CI/CD Overview" icon="arrows-spin" href="/v7/guides/ci-cd/overview">
|
|
573
|
+
CI/CD concepts
|
|
574
|
+
</Card>
|
|
575
|
+
|
|
576
|
+
<Card title="Performance" icon="gauge" href="/v7/guides/performance">
|
|
577
|
+
Optimize tests
|
|
578
|
+
</Card>
|
|
579
|
+
|
|
580
|
+
<Card title="Troubleshooting" icon="circle-question" href="/v7/guides/troubleshooting">
|
|
581
|
+
Common issues
|
|
582
|
+
</Card>
|
|
583
|
+
|
|
584
|
+
<Card title="Azure Pipelines Docs" icon="book" href="https://docs.microsoft.com/en-us/azure/devops/pipelines/">
|
|
585
|
+
Official docs
|
|
586
|
+
</Card>
|
|
587
|
+
</CardGroup>
|