testdriverai 7.2.44 → 7.2.45

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.
Files changed (36) hide show
  1. package/.github/workflows/acceptance-windows-scheduled.yaml +24 -15
  2. package/.github/workflows/acceptance.yaml +18 -16
  3. package/.github/workflows/windows-self-hosted.yaml +68 -0
  4. package/docs/v7/aws-setup.mdx +142 -144
  5. package/interfaces/cli/commands/init.js +1 -1
  6. package/lib/core/Dashcam.js +16 -16
  7. package/lib/vitest/hooks.mjs +13 -0
  8. package/lib/vitest/setup-aws.mjs +225 -0
  9. package/lib/vitest/setup-self-hosted.mjs +136 -0
  10. package/package.json +2 -1
  11. package/sdk.js +40 -9
  12. package/test/testdriver/ai.test.mjs +1 -1
  13. package/test/testdriver/assert.test.mjs +3 -1
  14. package/test/testdriver/chrome-extension.test.mjs +2 -2
  15. package/test/testdriver/drag-and-drop.test.mjs +1 -1
  16. package/test/testdriver/element-not-found.test.mjs +1 -1
  17. package/test/testdriver/exec-output.test.mjs +1 -1
  18. package/test/testdriver/exec-pwsh.test.mjs +1 -1
  19. package/test/testdriver/focus-window.test.mjs +1 -1
  20. package/test/testdriver/formatted-logging.test.mjs +1 -1
  21. package/test/testdriver/hover-image.test.mjs +2 -2
  22. package/test/testdriver/hover-text-with-description.test.mjs +2 -2
  23. package/test/testdriver/hover-text.test.mjs +1 -1
  24. package/test/testdriver/installer.test.mjs +2 -2
  25. package/test/testdriver/launch-vscode-linux.test.mjs +2 -2
  26. package/test/testdriver/match-image.test.mjs +2 -2
  27. package/test/testdriver/press-keys.test.mjs +1 -1
  28. package/test/testdriver/prompt.test.mjs +1 -1
  29. package/test/testdriver/scroll-keyboard.test.mjs +1 -1
  30. package/test/testdriver/scroll-until-image.test.mjs +1 -1
  31. package/test/testdriver/scroll-until-text.test.mjs +2 -2
  32. package/test/testdriver/scroll.test.mjs +1 -1
  33. package/test/testdriver/type.test.mjs +2 -2
  34. package/test/testdriver/windows-installer.test.mjs +1 -1
  35. package/vitest.config.mjs +4 -1
  36. package/setup/aws/self-hosted.yml +0 -111
@@ -12,33 +12,42 @@ on:
12
12
 
13
13
  jobs:
14
14
  test-windows:
15
+ uses: ./.github/workflows/windows-self-hosted.yaml
16
+ secrets:
17
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
18
+ TD_WEBSITE: ${{ secrets.TD_WEBSITE }}
19
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
20
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
21
+
22
+ sentry-and-publish:
23
+ needs: test-windows
15
24
  runs-on: ubuntu-latest
25
+ if: always()
16
26
 
17
27
  steps:
18
- - uses: actions/checkout@v4
19
-
20
- - name: Setup Node.js
21
- uses: actions/setup-node@v4
22
- with:
23
- node-version: '20'
24
- cache: 'npm'
25
-
26
- - name: Install dependencies
27
- run: npm ci
28
-
29
28
  - name: Install Sentry CLI
30
29
  run: npm install -g @sentry/cli
31
30
 
32
- - name: Run Windows tests with Sentry Cron monitoring
31
+ - name: Report to Sentry Cron
33
32
  run: |
34
- sentry-cli monitors run testdriver-windows-acceptance -- npx vitest run test/testdriver/*.test.mjs
33
+ sentry-cli monitors run testdriver-windows-acceptance -- echo "Windows tests completed"
35
34
  env:
36
35
  SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
37
- TD_API_KEY: ${{ secrets.TD_API_KEY }}
38
- TD_OS: windows
36
+
37
+ - name: Download test results
38
+ uses: actions/download-artifact@v4
39
+ with:
40
+ name: test-results-windows
39
41
 
40
42
  - name: Upload test results to Sentry Prevent
41
43
  if: ${{ !cancelled() }}
42
44
  uses: getsentry/prevent-action@v0
43
45
  with:
44
46
  token: ${{ secrets.SENTRY_PREVENT_TOKEN }}
47
+
48
+ - name: Publish Test Results
49
+ uses: EnricoMi/publish-unit-test-result-action@v2
50
+ if: always()
51
+ with:
52
+ files: test-report.junit.xml
53
+ check_name: Test Results (Windows Scheduled)
@@ -49,30 +49,32 @@ jobs:
49
49
  check_name: Test Results (Linux)
50
50
 
51
51
  test-windows:
52
- runs-on: ubuntu-latest
53
52
  if: contains(github.event.pull_request.labels.*.name, 'test-windows')
53
+ uses: ./.github/workflows/windows-self-hosted.yaml
54
+ with:
55
+ test_pattern: 'test/testdriver/assert.test.mjs'
56
+ secrets:
57
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
58
+ TD_WEBSITE: ${{ secrets.TD_WEBSITE }}
59
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
60
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
61
+
62
+ publish-windows-results:
63
+ needs: test-windows
64
+ runs-on: ubuntu-latest
65
+ if: always() && contains(github.event.pull_request.labels.*.name, 'test-windows')
54
66
 
55
67
  steps:
56
- - uses: actions/checkout@v4
57
-
58
- - name: Setup Node.js
59
- uses: actions/setup-node@v4
68
+ - name: Download test results
69
+ uses: actions/download-artifact@v4
60
70
  with:
61
- node-version: '20'
62
- cache: 'npm'
63
-
64
- - name: Install dependencies
65
- run: npm ci
66
-
67
- - name: Run Windows tests
68
- run: npx vitest run test/testdriver/*.test.mjs
69
- env:
70
- TD_API_KEY: ${{ secrets.TD_API_KEY }}
71
- TD_OS: windows
71
+ name: test-results-windows
72
72
 
73
73
  - name: Upload test results to Sentry Prevent
74
74
  if: ${{ !cancelled() }}
75
75
  uses: getsentry/prevent-action@v0
76
+ with:
77
+ token: ${{ secrets.SENTRY_PREVENT_TOKEN }}
76
78
 
77
79
  - name: Publish Test Results
78
80
  uses: EnricoMi/publish-unit-test-result-action@v2
@@ -0,0 +1,68 @@
1
+ name: Windows Self-Hosted Tests
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ test_pattern:
7
+ description: 'Test file pattern to run'
8
+ required: false
9
+ type: string
10
+ default: 'test/testdriver/*.test.mjs'
11
+ secrets:
12
+ TD_API_KEY:
13
+ required: true
14
+ TD_WEBSITE:
15
+ required: false
16
+ AWS_ACCESS_KEY_ID:
17
+ required: true
18
+ AWS_SECRET_ACCESS_KEY:
19
+ required: true
20
+
21
+ jobs:
22
+ test:
23
+ runs-on: ubuntu-latest
24
+
25
+ steps:
26
+ - name: Checkout repository
27
+ uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 0
30
+
31
+ - name: Set up Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: '20'
35
+ cache: 'npm'
36
+
37
+ - name: Install dependencies
38
+ run: npm ci
39
+
40
+ - name: Run Windows tests with self-hosted instances
41
+ run: npx vitest run ${{ inputs.test_pattern }}
42
+ env:
43
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
44
+ TD_WEBSITE: ${{ secrets.TD_WEBSITE }}
45
+ TD_OS: windows
46
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
47
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
48
+ AWS_REGION: us-east-2
49
+ AWS_LAUNCH_TEMPLATE_ID: lt-0ef9bf26a945fb442
50
+ AMI_ID: ami-063f575bb80f1e818
51
+ RESOLUTION: 1920x1080
52
+
53
+ - name: Upload test results
54
+ if: always()
55
+ uses: actions/upload-artifact@v4
56
+ with:
57
+ name: test-results-windows
58
+ path: test-report.junit.xml
59
+ retention-days: 30
60
+
61
+ - name: Upload TestDriver AI CLI logs
62
+ if: always()
63
+ uses: actions/upload-artifact@v4
64
+ with:
65
+ name: testdriverai-cli-logs-windows
66
+ path: /tmp/testdriverai-cli-*.log
67
+ if-no-files-found: warn
68
+ retention-days: 30
@@ -5,33 +5,63 @@ description: "Deploy TestDriver on your AWS infrastructure using CloudFormation"
5
5
  icon: "aws"
6
6
  ---
7
7
 
8
- This guide walks you through setting up self-hosted TestDriver instances on AWS. By the end, you'll have a complete infrastructure that can spawn test environments on-demand and integrate with your CI/CD pipelines.
8
+ This guide walks you through setting up self-hosted TestDriver instances on AWS. By the end, you'll have fully automated test infrastructure that spawns and terminates instances on-demand.
9
9
 
10
10
  ```mermaid
11
11
  graph LR
12
- A[Vitest] <--> B[api.testdriver.ai]
13
- B <--> C[Your AWS EC2 Instance]
12
+ A[Vitest Test] --> B[setup-aws hook]
13
+ B --> C[Spawns EC2]
14
+ C --> D[Runs Test]
15
+ D --> E[Terminates EC2]
14
16
  ```
15
17
 
18
+ ## How It Works
19
+
20
+ TestDriver automatically manages AWS EC2 instances for your tests:
21
+
22
+ 1. **Deploy CloudFormation** — One-time infrastructure setup
23
+ 2. **Configure Vitest** — Add one line to your config
24
+ 3. **Run Tests** — Instances spawn automatically, run tests, and terminate
25
+
26
+ That's it! No manual instance management needed.
27
+
16
28
  # Quickstart
17
29
 
18
- <Card
19
- title="Launch Stack"
20
- icon="aws"
21
- href="https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://v7-cloudformation-template.s3.us-east-2.amazonaws.com/cloudformation.yaml"
22
- horizontal
23
- arrow
24
- >
25
- Deploy TestDriver infrastructure with one click
26
- </Card>
30
+ <Steps>
31
+ <Step title="Deploy Infrastructure">
32
+ <Card
33
+ title="Launch CloudFormation Stack"
34
+ icon="aws"
35
+ href="https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://v7-cloudformation-template.s3.us-east-2.amazonaws.com/cloudformation.yaml"
36
+ horizontal
37
+ arrow
38
+ >
39
+ One-click AWS setup
40
+ </Card>
41
+ </Step>
42
+
43
+ <Step title="Add to Vitest Config">
44
+ ```javascript vitest.config.mjs
45
+ setupFiles: ['testdriverai/vitest/setup', 'testdriverai/vitest/setup-aws']
46
+ ```
47
+ </Step>
48
+
49
+ <Step title="Run Tests">
50
+ ```bash
51
+ TD_OS=windows AWS_REGION=us-east-2 \
52
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx AMI_ID=ami-xxx \
53
+ npx vitest run
54
+ ```
55
+ </Step>
56
+ </Steps>
27
57
 
28
58
  ## Overview
29
59
 
30
- The setup process involves three main steps:
60
+ The setup process is simple:
31
61
 
32
- 1. **CloudFormation Infrastructure** — Deploy our template to create VPC, security groups, IAM roles, and launch templates
33
- 2. **On-Demand Instance Spawning** — Use `spawn-runner.sh` to launch TestDriver instances when you need to run tests
34
- 3. **CI/CD Integration** — Automate the lifecycle in GitHub Actions: spawn instance → run tests → terminate instance
62
+ 1. **Deploy CloudFormation** — Creates VPC, security groups, IAM roles, and launch templates
63
+ 2. **Configure Vitest** — Add `setup-aws` to automatically manage instance lifecycle
64
+ 3. **Run Tests** — Set `TD_OS=windows` with AWS credentials and instances spawn/terminate automatically
35
65
 
36
66
 
37
67
  ## Prerequisites
@@ -127,35 +157,39 @@ Our CloudFormation template creates all the AWS infrastructure you need:
127
157
  </Tab>
128
158
  </Tabs>
129
159
 
130
- ## Step 2: Spawn Test Instances
131
-
132
- Use the [`spawn-runner.sh`](https://github.com/testdriverai/testdriverai/blob/main/setup/aws/spawn-runner.sh) script to launch instances on-demand. This script:
133
-
134
- - Launches a new EC2 instance using your launch template
135
- - Waits for the instance to be ready
136
- - Validates SSM connectivity
137
- - Returns instance details for test execution
138
-
139
- ```bash
140
- AWS_REGION=us-east-2 AMI_ID=ami-0504bf50fad62f312 AWS_LAUNCH_TEMPLATE_ID=lt-your-template-id sh setup/aws/spawn-runner.sh
141
- ```
142
-
143
- Output:
144
- ```
145
- PUBLIC_IP=1.2.3.4
146
- INSTANCE_ID=i-1234567890abcdef0
147
- AWS_REGION=us-east-2
160
+ ## Step 2: Configure Vitest
161
+
162
+ Add the AWS setup hook to your `vitest.config.mjs`:
163
+
164
+ ```javascript vitest.config.mjs
165
+ import { defineConfig } from 'vitest/config';
166
+ import { config } from 'dotenv';
167
+ import TestDriver from 'testdriverai/vitest';
168
+
169
+ config(); // Load .env file
170
+
171
+ export default defineConfig({
172
+ test: {
173
+ testTimeout: 900000,
174
+ hookTimeout: 900000,
175
+ maxConcurrency: 3,
176
+ reporters: [
177
+ 'default',
178
+ TestDriver(),
179
+ ['junit', { outputFile: 'test-report.junit.xml' }]
180
+ ],
181
+ setupFiles: ['testdriverai/vitest/setup', 'testdriverai/vitest/setup-aws'],
182
+ },
183
+ });
148
184
  ```
149
185
 
150
- ### Run Tests Against Your Instance
151
-
152
- Specify the instance IP using the `TD_IP` environment variable:
186
+ <Note>
187
+ **That's it!** The `setup-aws` hook automatically spawns and terminates instances when `TD_OS=windows` is set. No manual instance management needed.
188
+ </Note>
153
189
 
154
- ```bash
155
- TD_API_KEY=your-api-key TD_IP=1.2.3.4 npx vitest run
156
- ```
190
+ ## Step 3: Write Your Tests
157
191
 
158
- In your test file, pass the IP to TestDriver:
192
+ Tests should use `context.ip || process.env.TD_IP` for the IP configuration:
159
193
 
160
194
  ```javascript
161
195
  import { describe, it } from "vitest";
@@ -164,7 +198,7 @@ import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
164
198
  describe("My Test", () => {
165
199
  it("should run on self-hosted instance", async (context) => {
166
200
  const testdriver = TestDriver(context, {
167
- ip: process.env.TD_IP,
201
+ ip: context.ip || process.env.TD_IP,
168
202
  });
169
203
 
170
204
  await testdriver.provision.chrome({ url: "https://example.com" });
@@ -173,40 +207,42 @@ describe("My Test", () => {
173
207
  });
174
208
  ```
175
209
 
176
- ### Terminate Instances
210
+ <Note>
211
+ **How it works**: When `TD_OS=windows` with AWS credentials, `context.ip` is automatically set by the setup hook. When running without AWS setup (cloud-hosted), both are undefined and TestDriver uses the cloud. When `TD_IP` is provided manually, it takes precedence.
212
+ </Note>
177
213
 
178
- Always terminate instances after tests complete to avoid unnecessary costs:
214
+ ## Step 4: Run Tests
215
+
216
+ ### Locally
179
217
 
180
218
  ```bash
181
- aws ec2 terminate-instances \
182
- --instance-ids i-1234567890abcdef0 \
183
- --region us-east-2
219
+ TD_OS=windows \
220
+ AWS_REGION=us-east-2 \
221
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
222
+ AMI_ID=ami-0504bf50fad62f312 \
223
+ npx vitest run
184
224
  ```
185
225
 
186
226
  <Note>
187
- Instances are tagged with `Name=TestDriverRunner` and your `ProjectTag` for easy identification in the AWS console.
227
+ Each test gets its own fresh EC2 instance that's automatically terminated after completion.
188
228
  </Note>
189
229
 
190
- ## Step 3: GitHub Actions Integration
230
+ ### In GitHub Actions
191
231
 
192
- Automate the full lifecycle in your CI/CD pipeline. This workflow spawns an instance, runs tests, and terminates the instance:
232
+ Automate testing with self-hosted instances in your CI/CD pipeline. TestDriver automatically spawns a fresh instance for each test, runs the test, and terminates the instance.
193
233
 
194
234
  ```yaml .github/workflows/test.yml
195
- name: TestDriver Self-Hosted
235
+ name: TestDriver Self-Hosted Windows Tests
196
236
 
197
237
  on:
198
238
  push:
199
239
  branches: [main]
200
240
  pull_request:
201
241
 
202
- # Prevent concurrent runs from competing for resources
203
- concurrency:
204
- group: ${{ github.workflow }}-${{ github.ref }}
205
- cancel-in-progress: true
206
-
207
242
  jobs:
208
243
  test:
209
244
  runs-on: ubuntu-latest
245
+
210
246
  steps:
211
247
  - name: Checkout repository
212
248
  uses: actions/checkout@v4
@@ -215,43 +251,34 @@ jobs:
215
251
  uses: actions/setup-node@v4
216
252
  with:
217
253
  node-version: '20'
254
+ cache: 'npm'
218
255
 
219
256
  - name: Install dependencies
220
- run: npm install
221
-
222
- - name: Setup AWS Instance
223
- id: aws-setup
224
- run: |
225
- OUTPUT=$(./setup/aws/spawn-runner.sh | tee /dev/stderr)
226
- PUBLIC_IP=$(echo "$OUTPUT" | grep "PUBLIC_IP=" | cut -d'=' -f2)
227
- INSTANCE_ID=$(echo "$OUTPUT" | grep "INSTANCE_ID=" | cut -d'=' -f2)
228
- echo "public-ip=$PUBLIC_IP" >> $GITHUB_OUTPUT
229
- echo "instance-id=$INSTANCE_ID" >> $GITHUB_OUTPUT
257
+ run: npm ci
258
+
259
+ - name: Run Windows tests with self-hosted instances
260
+ run: npx vitest run test/testdriver/*.test.mjs
230
261
  env:
262
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
263
+ TD_OS: windows
231
264
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
232
265
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
233
- AWS_REGION: ${{ secrets.AWS_REGION }}
266
+ AWS_REGION: us-east-2
234
267
  AWS_LAUNCH_TEMPLATE_ID: ${{ secrets.AWS_LAUNCH_TEMPLATE_ID }}
235
268
  AMI_ID: ${{ secrets.AMI_ID }}
236
269
 
237
- - name: Run Tests
238
- run: npx vitest run
239
- env:
240
- TD_API_KEY: ${{ secrets.TD_API_KEY }}
241
- TD_IP: ${{ steps.aws-setup.outputs.public-ip }}
242
-
243
- - name: Shutdown AWS Instance
270
+ - name: Upload test results
244
271
  if: always()
245
- run: |
246
- aws ec2 terminate-instances \
247
- --region ${{ secrets.AWS_REGION }} \
248
- --instance-ids ${{ steps.aws-setup.outputs.instance-id }}
249
- env:
250
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
251
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
252
- AWS_REGION: ${{ secrets.AWS_REGION }}
272
+ uses: actions/upload-artifact@v4
273
+ with:
274
+ name: test-results
275
+ path: test-report.junit.xml
253
276
  ```
254
277
 
278
+ <Note>
279
+ **Automatic Instance Management**: Setting `TD_OS=windows` with AWS credentials enables automatic instance spawning. Each test gets its own fresh instance that's terminated after the test completes.
280
+ </Note>
281
+
255
282
  ### Required GitHub Secrets
256
283
 
257
284
  | Secret | Description | Example |
@@ -263,46 +290,58 @@ jobs:
263
290
  | `AMI_ID` | TestDriver AMI ID | `ami-0504bf50fad62f312` |
264
291
  | `TD_API_KEY` | Your TestDriver API key | From [console.testdriver.ai](https://console.testdriver.ai) |
265
292
 
266
- ### Example Workflow
267
-
268
- For a complete real-world example with matrix-based test execution and dynamic test file discovery, see the [`self-hosted.yml`](https://github.com/testdriverai/testdriverai/blob/main/setup/aws/self-hosted.yml) workflow in the TestDriver repository.
269
-
270
293
  <Tip>
271
- **Local Testing**: You can test your GitHub Actions workflow locally using [nektos/act](https://github.com/nektos/act). The `self-hosted.yml` workflow includes commented lines for installing the AWS CLI when running with `act`.
294
+ Add these as **GitHub Repository Secrets** under Settings Secrets and variables Actions
272
295
  </Tip>
273
296
 
274
- ## Manual Instance Management
297
+ ### Example Workflows
275
298
 
276
- You can manage TestDriver instances manually through the AWS Console or CLI. This is useful for debugging, development, or running tests outside of CI/CD.
299
+ For complete production examples, see:
300
+ - **[Scheduled Tests](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/acceptance-windows-scheduled.yaml)** — Daily automated test runs
301
+ - **[Reusable Workflow](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/windows-self-hosted.yaml)** — Shared configuration for PR and scheduled tests
277
302
 
278
- ### Starting an Instance
303
+ ## Advanced Usage
279
304
 
280
- ```bash
281
- aws ec2 run-instances \
282
- --region us-east-2 \
283
- --image-id ami-0504bf50fad62f312 \
284
- --launch-template LaunchTemplateId=lt-your-template-id \
285
- --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=testdriver-manual}]'
286
- ```
305
+ ### Using an Existing Instance
287
306
 
288
- ### Stopping an Instance
307
+ If you already have a running instance, you can skip automatic spawning by providing `TD_IP`:
289
308
 
290
309
  ```bash
291
- aws ec2 stop-instances --region us-east-2 --instance-ids i-1234567890abcdef0
310
+ TD_OS=windows TD_IP=1.2.3.4 npx vitest run
292
311
  ```
293
312
 
294
- ### Starting a Stopped Instance
313
+ The `setup-aws` hook will detect `TD_IP` is already set and skip spawning a new instance.
314
+
315
+ ### Manual Instance Management
316
+
317
+ For advanced use cases, you can manually spawn instances using the [`spawn-runner.sh`](https://github.com/testdriverai/testdriverai/blob/main/setup/aws/spawn-runner.sh) script:
295
318
 
296
319
  ```bash
297
- aws ec2 start-instances --region us-east-2 --instance-ids i-1234567890abcdef0
320
+ AWS_REGION=us-east-2 \
321
+ AMI_ID=ami-0504bf50fad62f312 \
322
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
323
+ bash setup/aws/spawn-runner.sh
298
324
  ```
299
325
 
300
- ### Terminating Instances
326
+ Output:
327
+ ```
328
+ PUBLIC_IP=1.2.3.4
329
+ INSTANCE_ID=i-1234567890abcdef0
330
+ AWS_REGION=us-east-2
331
+ ```
332
+
333
+ Then manually terminate when done:
301
334
 
302
335
  ```bash
303
- aws ec2 terminate-instances --region us-east-2 --instance-ids i-1234567890abcdef0
336
+ aws ec2 terminate-instances \
337
+ --instance-ids i-1234567890abcdef0 \
338
+ --region us-east-2
304
339
  ```
305
340
 
341
+ For complete production examples, see:
342
+ - **[Scheduled Tests](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/acceptance-windows-scheduled.yaml)** — Daily automated test runs
343
+ - **[Reusable Workflow](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/windows-self-hosted.yaml)** — Shared configuration for PR and scheduled tests
344
+
306
345
  ### Connecting to an Instance
307
346
 
308
347
  You can connect to running instances via:
@@ -355,28 +394,6 @@ You can customize the AMI to include additional software or configurations:
355
394
  **Security**: Never use the default password in production. Always rotate passwords before creating custom AMIs.
356
395
  </Warning>
357
396
 
358
- ### Changing Screen Resolution
359
-
360
- Set resolution via environment variable when spawning:
361
-
362
- ```bash
363
- export RESOLUTION=1920x1080
364
- ./setup/aws/spawn-runner.sh
365
- ```
366
-
367
- Or in a lifecycle provision script:
368
-
369
- ```yaml lifecycle/provision.yaml
370
- version: 7.0.0
371
- steps:
372
- - prompt: set screen resolution
373
- commands:
374
- - command: exec
375
- lang: pwsh
376
- code: |
377
- C:\testdriver\SetResolution.ps1 -Width 1920 -Height 1080
378
- ```
379
-
380
397
  ## Security Best Practices
381
398
 
382
399
  ### Network Security
@@ -430,22 +447,3 @@ See [GitHub's OIDC documentation](https://docs.github.com/en/actions/deployment/
430
447
  - Validate credentials and permissions
431
448
  - Check service quotas and limits
432
449
  - Verify region consistency across all resources
433
-
434
- ## Getting Help
435
-
436
- <CardGroup cols={2}>
437
- <Card
438
- title="Contact Support"
439
- icon="envelope"
440
- href="https://calendly.com/d/cq23-qyn-3v6/testdriver-ai-demo"
441
- >
442
- Get help with self-hosted setup and configuration
443
- </Card>
444
- <Card
445
- title="Self-Hosted Overview"
446
- icon="server"
447
- href="/v7/self-hosted"
448
- >
449
- Learn more about self-hosted benefits and pricing
450
- </Card>
451
- </CardGroup>
@@ -199,7 +199,7 @@ export async function login(testdriver) {
199
199
 
200
200
  // Find the username field
201
201
  const usernameField = await testdriver.find(
202
- 'Username, label above the username input field on the login form'
202
+ 'username input'
203
203
  );
204
204
  await usernameField.click();
205
205