testdriverai 7.3.12 → 7.3.13

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 (133) hide show
  1. package/.github/skills/testdriver:ai/SKILL.md +204 -0
  2. package/.github/skills/testdriver:assert/SKILL.md +284 -0
  3. package/.github/skills/testdriver:aws-setup/SKILL.md +515 -0
  4. package/.github/skills/testdriver:caching/SKILL.md +124 -0
  5. package/.github/skills/testdriver:captcha/SKILL.md +159 -0
  6. package/.github/skills/testdriver:ci-cd/SKILL.md +602 -0
  7. package/.github/skills/testdriver:click/SKILL.md +286 -0
  8. package/.github/skills/testdriver:client/SKILL.md +339 -0
  9. package/.github/skills/testdriver:cloud/SKILL.md +119 -0
  10. package/.github/skills/testdriver:customizing-devices/SKILL.md +153 -0
  11. package/.github/skills/testdriver:dashcam/SKILL.md +418 -0
  12. package/.github/skills/testdriver:debugging-with-screenshots/SKILL.md +271 -0
  13. package/.github/skills/testdriver:device-config/SKILL.md +317 -0
  14. package/.github/skills/testdriver:double-click/SKILL.md +102 -0
  15. package/.github/skills/testdriver:elements/SKILL.md +605 -0
  16. package/.github/skills/testdriver:enterprise/SKILL.md +114 -0
  17. package/.github/skills/testdriver:examples/SKILL.md +7 -0
  18. package/.github/skills/testdriver:exec/SKILL.md +345 -0
  19. package/.github/skills/testdriver:find/SKILL.md +721 -0
  20. package/.github/skills/testdriver:focus-application/SKILL.md +293 -0
  21. package/.github/skills/testdriver:generating-tests/SKILL.md +36 -0
  22. package/.github/skills/testdriver:hover/SKILL.md +278 -0
  23. package/.github/skills/testdriver:locating-elements/SKILL.md +71 -0
  24. package/.github/skills/testdriver:making-assertions/SKILL.md +32 -0
  25. package/.github/skills/testdriver:mcp-workflow/SKILL.md +410 -0
  26. package/.github/skills/testdriver:mouse-down/SKILL.md +161 -0
  27. package/.github/skills/testdriver:mouse-up/SKILL.md +164 -0
  28. package/.github/skills/testdriver:performing-actions/SKILL.md +51 -0
  29. package/.github/skills/testdriver:press-keys/SKILL.md +348 -0
  30. package/.github/skills/testdriver:quickstart/SKILL.md +161 -0
  31. package/.github/skills/testdriver:reusable-code/SKILL.md +240 -0
  32. package/.github/skills/testdriver:right-click/SKILL.md +123 -0
  33. package/.github/skills/testdriver:running-tests/SKILL.md +181 -0
  34. package/.github/skills/testdriver:screenshot/SKILL.md +167 -0
  35. package/.github/skills/testdriver:scroll/SKILL.md +299 -0
  36. package/.github/skills/testdriver:secrets/SKILL.md +115 -0
  37. package/.github/skills/testdriver:self-hosted/SKILL.md +65 -0
  38. package/.github/skills/testdriver:test-writer/SKILL.md +451 -0
  39. package/.github/skills/testdriver:testdriver/SKILL.md +523 -0
  40. package/.github/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
  41. package/.github/skills/testdriver:type/SKILL.md +357 -0
  42. package/.github/skills/testdriver:variables/SKILL.md +111 -0
  43. package/.github/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
  44. package/.github/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
  45. package/.github/workflows/acceptance-windows-scheduled.yaml +6 -1
  46. package/.github/workflows/acceptance.yaml +0 -36
  47. package/.github/workflows/update-examples.yaml +53 -0
  48. package/CHANGELOG.md +4 -0
  49. package/agent/events.js +1 -0
  50. package/agent/index.js +8 -0
  51. package/agent/lib/commands.js +48 -29
  52. package/agent/lib/redraw.js +3 -1
  53. package/agent/lib/sandbox.js +166 -14
  54. package/agent/lib/sdk.js +142 -3
  55. package/agent/lib/system.js +4 -6
  56. package/ai/skills/testdriver:ai/SKILL.md +204 -0
  57. package/ai/skills/testdriver:assert/SKILL.md +315 -0
  58. package/ai/skills/testdriver:aws-setup/SKILL.md +448 -0
  59. package/ai/skills/testdriver:caching/SKILL.md +124 -0
  60. package/ai/skills/testdriver:captcha/SKILL.md +159 -0
  61. package/ai/skills/testdriver:ci-cd/SKILL.md +602 -0
  62. package/ai/skills/testdriver:click/SKILL.md +286 -0
  63. package/ai/skills/testdriver:client/SKILL.md +372 -0
  64. package/ai/skills/testdriver:cloud/SKILL.md +119 -0
  65. package/ai/skills/testdriver:customizing-devices/SKILL.md +153 -0
  66. package/ai/skills/testdriver:dashcam/SKILL.md +418 -0
  67. package/ai/skills/testdriver:debugging-with-screenshots/SKILL.md +401 -0
  68. package/ai/skills/testdriver:device-config/SKILL.md +317 -0
  69. package/ai/skills/testdriver:double-click/SKILL.md +102 -0
  70. package/ai/skills/testdriver:elements/SKILL.md +605 -0
  71. package/ai/skills/testdriver:enterprise/SKILL.md +114 -0
  72. package/ai/skills/testdriver:examples/SKILL.md +7 -0
  73. package/ai/skills/testdriver:exec/SKILL.md +345 -0
  74. package/ai/skills/testdriver:find/SKILL.md +745 -0
  75. package/ai/skills/testdriver:focus-application/SKILL.md +293 -0
  76. package/ai/skills/testdriver:generating-tests/SKILL.md +36 -0
  77. package/ai/skills/testdriver:hover/SKILL.md +278 -0
  78. package/ai/skills/testdriver:locating-elements/SKILL.md +71 -0
  79. package/ai/skills/testdriver:making-assertions/SKILL.md +32 -0
  80. package/ai/skills/testdriver:mcp-workflow/SKILL.md +410 -0
  81. package/ai/skills/testdriver:mouse-down/SKILL.md +161 -0
  82. package/ai/skills/testdriver:mouse-up/SKILL.md +164 -0
  83. package/ai/skills/testdriver:ocr/SKILL.md +235 -0
  84. package/ai/skills/testdriver:performing-actions/SKILL.md +51 -0
  85. package/ai/skills/testdriver:press-keys/SKILL.md +348 -0
  86. package/ai/skills/testdriver:quickstart/SKILL.md +146 -0
  87. package/ai/skills/testdriver:reusable-code/SKILL.md +240 -0
  88. package/ai/skills/testdriver:right-click/SKILL.md +123 -0
  89. package/ai/skills/testdriver:running-tests/SKILL.md +185 -0
  90. package/ai/skills/testdriver:screenshot/SKILL.md +248 -0
  91. package/ai/skills/testdriver:scroll/SKILL.md +335 -0
  92. package/ai/skills/testdriver:secrets/SKILL.md +115 -0
  93. package/ai/skills/testdriver:self-hosted/SKILL.md +65 -0
  94. package/ai/skills/testdriver:test-writer/SKILL.md +451 -0
  95. package/ai/skills/testdriver:testdriver/SKILL.md +631 -0
  96. package/ai/skills/testdriver:testdriver-mechanic/SKILL.md +165 -0
  97. package/ai/skills/testdriver:type/SKILL.md +357 -0
  98. package/ai/skills/testdriver:variables/SKILL.md +111 -0
  99. package/ai/skills/testdriver:waiting-for-elements/SKILL.md +66 -0
  100. package/ai/skills/testdriver:what-is-testdriver/SKILL.md +54 -0
  101. package/debugger/index.html +12 -2
  102. package/docs/v7/examples/scroll-keyboard.mdx +1 -1
  103. package/docs/v7/find.mdx +1 -0
  104. package/examples/config.mjs +1 -1
  105. package/examples/findall-coffee-icons.test.mjs +42 -0
  106. package/examples/flake-diffthreshold-001.test.mjs +9 -0
  107. package/examples/flake-diffthreshold-01.test.mjs +9 -0
  108. package/examples/flake-diffthreshold-05.test.mjs +9 -0
  109. package/examples/{z_flake-noredraw-cache.test.mjs → flake-noredraw-cache.test.mjs} +2 -2
  110. package/examples/{z_flake-noredraw-nocache.test.mjs → flake-noredraw-nocache.test.mjs} +2 -2
  111. package/examples/{z_flake-redraw-cache.test.mjs → flake-redraw-cache.test.mjs} +2 -2
  112. package/examples/{z_flake-redraw-nocache.test.mjs → flake-redraw-nocache.test.mjs} +2 -2
  113. package/examples/flake-rocket-match.test.mjs +30 -0
  114. package/examples/{z_flake-shared.mjs → flake-shared.mjs} +2 -2
  115. package/examples/parse.test.mjs +19 -0
  116. package/examples/scroll-keyboard.test.mjs +1 -1
  117. package/interfaces/cli/lib/base.js +6 -0
  118. package/interfaces/logger.js +51 -13
  119. package/interfaces/vitest-plugin.mjs +137 -0
  120. package/lib/core/index.d.ts +22 -0
  121. package/lib/init-project.js +105 -6
  122. package/lib/vitest/hooks.mjs +2 -5
  123. package/lib/vitest/setup-disable-defender.mjs +52 -0
  124. package/package.json +2 -1
  125. package/sdk-log-formatter.js +90 -0
  126. package/sdk.d.ts +88 -51
  127. package/sdk.js +126 -18
  128. package/setup/aws/disable-defender.sh +42 -0
  129. package/vitest.config.mjs +1 -3
  130. package/examples/z_flake-diffthreshold-001.test.mjs +0 -9
  131. package/examples/z_flake-diffthreshold-01.test.mjs +0 -9
  132. package/examples/z_flake-diffthreshold-05.test.mjs +0 -9
  133. /package/{examples → manual}/captcha-api.test.mjs +0 -0
@@ -0,0 +1,515 @@
1
+ ---
2
+ name: testdriver:aws-setup
3
+ description: Deploy TestDriver on your AWS infrastructure using CloudFormation
4
+ ---
5
+ <!-- Generated from aws-setup.mdx. DO NOT EDIT. -->
6
+
7
+ 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.
8
+
9
+ ```mermaid
10
+ graph LR
11
+ A[Vitest Test] --> B[setup-aws hook]
12
+ B --> C[Spawns EC2]
13
+ C --> D[Runs Test]
14
+ D --> E[Terminates EC2]
15
+ ```
16
+
17
+ ## How It Works
18
+
19
+ TestDriver automatically manages AWS EC2 instances for your tests:
20
+
21
+ 1. **Deploy CloudFormation** — One-time infrastructure setup
22
+ 2. **Configure Vitest** — Add one line to your config
23
+ 3. **Run Tests** — Instances spawn automatically, run tests, and terminate
24
+
25
+ That's it! No manual instance management needed.
26
+
27
+ # Quickstart
28
+
29
+ <Steps>
30
+ <Step title="Deploy Infrastructure">
31
+ <Card
32
+ title="Launch CloudFormation Stack"
33
+ icon="aws"
34
+ href="https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://v7-cloudformation-template.s3.us-east-2.amazonaws.com/cloudformation.yaml"
35
+ horizontal
36
+ arrow
37
+ >
38
+ One-click AWS setup
39
+ </Card>
40
+ </Step>
41
+
42
+ <Step title="Add to Vitest Config">
43
+ ```javascript vitest.config.mjs
44
+ setupFiles: ['testdriverai/vitest/setup', 'testdriverai/vitest/setup-aws']
45
+ ```
46
+ </Step>
47
+
48
+ <Step title="Run Tests">
49
+ ```bash
50
+ TD_OS=windows AWS_REGION=us-east-2 \
51
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx AMI_ID=ami-xxx \
52
+ vitest run
53
+ ```
54
+ </Step>
55
+ </Steps>
56
+
57
+ ## Overview
58
+
59
+ The setup process is simple:
60
+
61
+ 1. **Deploy CloudFormation** — Creates VPC, security groups, IAM roles, and launch templates
62
+ 2. **Configure Vitest** — Add `setup-aws` to automatically manage instance lifecycle
63
+ 3. **Run Tests** — Set `TD_OS=windows` with AWS credentials and instances spawn/terminate automatically
64
+
65
+
66
+ ## Prerequisites
67
+
68
+ Before you begin, ensure you have:
69
+
70
+ - AWS account with CloudFormation permissions
71
+ - [AWS CLI](https://aws.amazon.com/cli/) installed and configured (`aws configure`)
72
+ - Access to the TestDriver AMI — [Contact us](http://testdriver.ai/demo) with your AWS region
73
+ - A GitHub repository for your tests
74
+
75
+ <Tip>
76
+ The TestDriver Golden Image AMI ID is `ami-0504bf50fad62f312`. Contact us to get access in your preferred AWS region.
77
+ </Tip>
78
+
79
+ ## Step 1: Deploy CloudFormation Stack
80
+
81
+ Our CloudFormation template creates all the AWS infrastructure you need:
82
+
83
+ - Dedicated VPC with public subnet
84
+ - Security group with required port access
85
+ - IAM roles and instance profiles
86
+ - EC2 launch template for instance creation
87
+
88
+ <Tabs>
89
+ <Tab title="GUI">
90
+ Click the button below to launch the CloudFormation stack in your AWS Console:
91
+
92
+ <Card
93
+ title="Launch Stack"
94
+ icon="aws"
95
+ href="https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://v7-cloudformation-template.s3.us-east-2.amazonaws.com/cloudformation.yaml"
96
+ horizontal
97
+ arrow
98
+ >
99
+ Deploy TestDriver infrastructure with one click
100
+ </Card>
101
+
102
+ Configure the stack parameters:
103
+ - **Stack name**: `testdriver-infrastructure` (or your preferred name)
104
+ - **ProjectTag**: `testdriver`
105
+ - **AllowedIngressCidr**: Your IP range (e.g., `203.0.113.0/24`)
106
+ - **InstanceType**: `c5.xlarge` (recommended)
107
+ - **CreateKeyPair**: `true`
108
+
109
+ <Warning>
110
+ **Security**: Replace `AllowedIngressCidr` with your specific IP ranges to restrict VPC access. Avoid using `0.0.0.0/0` in production.
111
+ </Warning>
112
+
113
+ ### Get Your Launch Template ID
114
+
115
+ After the stack creation completes, navigate to the **Outputs** tab to find your `LaunchTemplateId`:
116
+
117
+ ![Launch Template ID](/images/content/self-hosted/launchtemplateid.png)
118
+
119
+ <Tip>
120
+ **Save this ID** — you'll need it for spawning instances and CI configuration.
121
+ </Tip>
122
+ </Tab>
123
+ <Tab title="CLI">
124
+ Download the template from the [TestDriver CLI repository](https://github.com/testdriverai/testdriverai/blob/main/setup/aws/cloudformation.yaml), then deploy:
125
+
126
+ ```bash
127
+ aws cloudformation deploy \
128
+ --template-file setup/aws/cloudformation.yaml \
129
+ --stack-name testdriver-infrastructure \
130
+ --parameter-overrides \
131
+ ProjectTag=testdriver \
132
+ AllowedIngressCidr=0.0.0.0/0 \
133
+ InstanceType=c5.xlarge \
134
+ CreateKeyPair=true \
135
+ --capabilities CAPABILITY_IAM
136
+ ```
137
+
138
+ <Warning>
139
+ **Security**: Replace `AllowedIngressCidr=0.0.0.0/0` with your specific IP ranges to restrict VPC access.
140
+ </Warning>
141
+
142
+ ### Get Your Launch Template ID
143
+
144
+ After deployment completes, retrieve the launch template ID:
145
+
146
+ ```bash
147
+ aws cloudformation describe-stacks \
148
+ --stack-name testdriver-infrastructure \
149
+ --query 'Stacks[0].Outputs[?OutputKey==`LaunchTemplateId`].OutputValue' \
150
+ --output text
151
+ ```
152
+
153
+ <Tip>
154
+ **Save this ID** — you'll need it for spawning instances and CI configuration.
155
+ </Tip>
156
+ </Tab>
157
+ </Tabs>
158
+
159
+ ## Step 2: Configure Vitest
160
+
161
+ Add the AWS setup hook to your `vitest.config.mjs`:
162
+
163
+ ```javascript vitest.config.mjs
164
+ import { defineConfig } from 'vitest/config';
165
+ import { config } from 'dotenv';
166
+ import TestDriver from 'testdriverai/vitest';
167
+
168
+ config(); // Load .env file
169
+
170
+ export default defineConfig({
171
+ test: {
172
+ testTimeout: 900000,
173
+ hookTimeout: 900000,
174
+ maxConcurrency: 3,
175
+ reporters: [
176
+ 'default',
177
+ TestDriver(),
178
+ ['junit', { outputFile: 'test-report.junit.xml' }]
179
+ ],
180
+ setupFiles: ['testdriverai/vitest/setup', 'testdriverai/vitest/setup-aws'],
181
+ },
182
+ });
183
+ ```
184
+
185
+ <Note>
186
+ **That's it!** The `setup-aws` hook automatically spawns and terminates instances when `TD_OS=windows` is set. No manual instance management needed.
187
+ </Note>
188
+
189
+ ## Step 3: Write Your Tests
190
+
191
+ Tests should use `context.ip || process.env.TD_IP` for the IP configuration:
192
+
193
+ ```javascript
194
+ import { describe, it } from "vitest";
195
+ import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
196
+
197
+ describe("My Test", () => {
198
+ it("should run on self-hosted instance", async (context) => {
199
+ const testdriver = TestDriver(context, {
200
+ ip: context.ip || process.env.TD_IP,
201
+ });
202
+
203
+ await testdriver.provision.chrome({ url: "https://example.com" });
204
+ // ... your test steps
205
+ });
206
+ });
207
+ ```
208
+
209
+ <Note>
210
+ **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.
211
+ </Note>
212
+
213
+ ## Step 4: Run Tests
214
+
215
+ ### Locally
216
+
217
+ ```bash
218
+ TD_OS=windows \
219
+ AWS_REGION=us-east-2 \
220
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
221
+ AMI_ID=ami-0504bf50fad62f312 \
222
+ vitest run
223
+ ```
224
+
225
+ <Note>
226
+ Each test gets its own fresh EC2 instance that's automatically terminated after completion.
227
+ </Note>
228
+
229
+ ### In GitHub Actions
230
+
231
+ 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.
232
+
233
+ ```yaml .github/workflows/test.yml
234
+ name: TestDriver Self-Hosted Windows Tests
235
+
236
+ on:
237
+ push:
238
+ branches: [main]
239
+ pull_request:
240
+
241
+ jobs:
242
+ test:
243
+ runs-on: ubuntu-latest
244
+
245
+ steps:
246
+ - name: Checkout repository
247
+ uses: actions/checkout@v4
248
+
249
+ - name: Setup Node.js
250
+ uses: actions/setup-node@v4
251
+ with:
252
+ node-version: '20'
253
+ cache: 'npm'
254
+
255
+ - name: Install dependencies
256
+ run: npm ci
257
+
258
+ - name: Run Windows tests with self-hosted instances
259
+ run: vitest run examples/*.test.mjs
260
+ env:
261
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
262
+ TD_OS: windows
263
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
264
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
265
+ AWS_REGION: us-east-2
266
+ AWS_LAUNCH_TEMPLATE_ID: ${{ secrets.AWS_LAUNCH_TEMPLATE_ID }}
267
+ AMI_ID: ${{ secrets.AMI_ID }}
268
+
269
+ - name: Upload test results
270
+ if: always()
271
+ uses: actions/upload-artifact@v4
272
+ with:
273
+ name: test-results
274
+ path: test-report.junit.xml
275
+ ```
276
+
277
+ <Note>
278
+ **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.
279
+ </Note>
280
+
281
+ ### Required GitHub Secrets
282
+
283
+ | Secret | Description | Example |
284
+ |--------|-------------|---------|
285
+ | `AWS_ACCESS_KEY_ID` | AWS access key | `AKIAIOSFODNN7EXAMPLE` |
286
+ | `AWS_SECRET_ACCESS_KEY` | AWS secret key | `wJalrXUtnFEMI/K7MDENG...` |
287
+ | `AWS_REGION` | AWS region | `us-east-2` |
288
+ | `AWS_LAUNCH_TEMPLATE_ID` | From CloudFormation output | `lt-07c53ce8349b958d1` |
289
+ | `AMI_ID` | TestDriver AMI ID | `ami-0504bf50fad62f312` |
290
+ | `TD_API_KEY` | Your TestDriver API key | From [console.testdriver.ai](https://console.testdriver.ai) |
291
+
292
+ <Tip>
293
+ Add these as **GitHub Repository Secrets** under Settings → Secrets and variables → Actions
294
+ </Tip>
295
+
296
+ ### Example Workflows
297
+
298
+ For complete production examples, see:
299
+ - **[Scheduled Tests](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/acceptance-windows-scheduled.yaml)** — Daily automated test runs
300
+ - **[Reusable Workflow](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/windows-self-hosted.yaml)** — Shared configuration for PR and scheduled tests
301
+
302
+ ## Advanced Usage
303
+
304
+ ### Using an Existing Instance
305
+
306
+ If you already have a running instance, you can skip automatic spawning by providing `TD_IP`:
307
+
308
+ ```bash
309
+ TD_OS=windows TD_IP=1.2.3.4 vitest run
310
+ ```
311
+
312
+ The `setup-aws` hook will detect `TD_IP` is already set and skip spawning a new instance.
313
+
314
+ ### Manual Instance Management
315
+
316
+ 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:
317
+
318
+ ```bash
319
+ AWS_REGION=us-east-2 \
320
+ AMI_ID=ami-0504bf50fad62f312 \
321
+ AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
322
+ bash setup/aws/spawn-runner.sh
323
+ ```
324
+
325
+ Output:
326
+ ```
327
+ PUBLIC_IP=1.2.3.4
328
+ INSTANCE_ID=i-1234567890abcdef0
329
+ AWS_REGION=us-east-2
330
+ ```
331
+
332
+ Then manually terminate when done:
333
+
334
+ ```bash
335
+ aws ec2 terminate-instances \
336
+ --instance-ids i-1234567890abcdef0 \
337
+ --region us-east-2
338
+ ```
339
+
340
+ For complete production examples, see:
341
+ - **[Scheduled Tests](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/acceptance-windows-scheduled.yaml)** — Daily automated test runs
342
+ - **[Reusable Workflow](https://github.com/testdriverai/testdriverai/blob/main/.github/workflows/windows-self-hosted.yaml)** — Shared configuration for PR and scheduled tests
343
+
344
+ ### Connecting to an Instance
345
+
346
+ You can connect to running instances via:
347
+ - **RDP** — Use the public IP on port 3389
348
+ - **VNC** — Access via web browser at `http://<public-ip>:5900`
349
+ - **AWS Console** — Use EC2 Instance Connect or Session Manager
350
+
351
+ <Note>
352
+ Stopped instances retain their EBS volumes and can be restarted later. Terminated instances are permanently deleted. Always terminate instances when done to avoid storage costs.
353
+ </Note>
354
+
355
+ ## AMI Customization
356
+
357
+ The TestDriver Golden Image comes pre-configured with:
358
+
359
+ - Windows Server with desktop environment
360
+ - VNC + web server for remote access
361
+ - Python, Node.js, Git
362
+ - TestDriver agent and dependencies
363
+
364
+ ### Creating a Custom AMI
365
+
366
+ You can customize the AMI to include additional software or configurations:
367
+
368
+ <Steps>
369
+ <Step title="Connect via RDP">
370
+ Use the default credentials:
371
+ - **Username**: `testdriver`
372
+ - **Password**: `changemeABC123`
373
+ </Step>
374
+
375
+ <Step title="Change the Password">
376
+ **Critical**: Run the password rotation script immediately:
377
+ ```powershell
378
+ C:\testdriver\RotateLocalPasswords.ps1
379
+ ```
380
+ Save the new password securely.
381
+ </Step>
382
+
383
+ <Step title="Install Your Software">
384
+ Install any additional dependencies, configure settings, or modify the environment as needed.
385
+ </Step>
386
+
387
+ <Step title="Create New AMI">
388
+ Use the AWS console or CLI to create an AMI from your modified instance. Update your workflow to use the new AMI ID.
389
+ </Step>
390
+ </Steps>
391
+
392
+ <Warning>
393
+ **Security**: Never use the default password in production. Always rotate passwords before creating custom AMIs.
394
+ </Warning>
395
+
396
+ ## Custom Lifecycle Hooks
397
+
398
+ You can run custom scripts after instance spawning by creating your own Vitest setup file. This is useful for:
399
+
400
+ - Installing additional software via SSM before tests run
401
+ - Configuring network settings or proxies
402
+ - Running cleanup scripts after tests complete
403
+ - Collecting logs or artifacts from instances
404
+
405
+ ### Post-Spawn Hooks
406
+
407
+ To run commands after the instance is ready but before the test executes, create a setup file positioned **after** `setup-aws`:
408
+
409
+ ```javascript post-spawn-setup.mjs
410
+ import { execSync } from 'child_process';
411
+ import { beforeEach } from 'vitest';
412
+
413
+ beforeEach(async (context) => {
414
+ // context.ip is set by setup-aws
415
+ if (!context.ip) return;
416
+
417
+ console.log(`Instance ready at ${context.ip}, running post-spawn setup...`);
418
+
419
+ // Run SSM commands on the instance
420
+ execSync(`aws ssm send-command \
421
+ --region "${process.env.AWS_REGION}" \
422
+ --targets "Key=tag:Name,Values=td-*" \
423
+ --document-name "AWS-RunPowerShellScript" \
424
+ --parameters 'commands=["choco install my-software -y"]'`);
425
+ });
426
+ ```
427
+
428
+ ```javascript vitest.config.mjs
429
+ setupFiles: [
430
+ 'testdriverai/vitest/setup',
431
+ 'testdriverai/vitest/setup-aws', // Instance spawns here
432
+ './post-spawn-setup.mjs' // Your hooks run AFTER instance is ready
433
+ ]
434
+ ```
435
+
436
+ <Note>
437
+ Vitest executes setup files in array order. By positioning your file after `setup-aws`, the `context.ip` is already available in your `beforeEach` hook.
438
+ </Note>
439
+
440
+ ### Post-Test Cleanup
441
+
442
+ To run cleanup after each test completes (while the instance is still running):
443
+
444
+ ```javascript post-spawn-setup.mjs
445
+ import { execSync } from 'child_process';
446
+ import { beforeEach, afterEach } from 'vitest';
447
+
448
+ beforeEach(async (context) => {
449
+ if (!context.ip) return;
450
+ // ... post-spawn setup
451
+ });
452
+
453
+ afterEach(async (context) => {
454
+ if (!context.ip) return;
455
+
456
+ console.log('Running post-test cleanup...');
457
+ execSync('./scripts/collect-logs.sh', {
458
+ env: { ...process.env, INSTANCE_IP: context.ip }
459
+ });
460
+ });
461
+ ```
462
+
463
+ ## Security Best Practices
464
+
465
+ ### Network Security
466
+
467
+ - **Restrict CIDR blocks** — Only allow access from known IP ranges
468
+ - **Use VPC endpoints** — For private AWS service communication
469
+ - **Enable VPC Flow Logs** — For network monitoring
470
+
471
+ ### AWS Authentication
472
+
473
+ Use OIDC instead of long-term credentials for GitHub Actions:
474
+
475
+ ```yaml
476
+ permissions:
477
+ id-token: write
478
+ contents: read
479
+
480
+ steps:
481
+ - name: Configure AWS credentials
482
+ uses: aws-actions/configure-aws-credentials@v4
483
+ with:
484
+ role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
485
+ aws-region: us-east-2
486
+ ```
487
+
488
+ See [GitHub's OIDC documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) for setup instructions.
489
+
490
+ ### Instance Security
491
+
492
+ - **Terminate immediately** after tests complete
493
+ - **Monitor costs** with AWS billing alerts
494
+ - **Use least-privilege IAM roles**
495
+ - **Enable CloudTrail** for audit logging
496
+
497
+ ## Troubleshooting
498
+
499
+ ### Instance Not Responding
500
+
501
+ - **Check security groups** — Verify required ports are open (RDP 3389, VNC 5900, TestDriver ports)
502
+ - **Verify status checks** — Ensure instance has passed AWS status checks
503
+ - **Check AMI compatibility** — Some instance types don't support certain AMIs
504
+
505
+ ### Connection Timeouts
506
+
507
+ - Verify network connectivity from CI runner to instance
508
+ - Check VPC routing and internet gateway configuration
509
+ - Confirm instance is in the correct subnet
510
+
511
+ ### AWS CLI Errors
512
+
513
+ - Validate credentials and permissions
514
+ - Check service quotas and limits
515
+ - Verify region consistency across all resources
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: testdriver:caching
3
+ description: 1.7x faster test execution with intelligent caching and optimization
4
+ ---
5
+ <!-- Generated from caching.mdx. DO NOT EDIT. -->
6
+
7
+ TestDriver is engineered for performance with intelligent caching that delivers up to **1.7x faster** test execution by skipping redundant AI vision analysis.
8
+
9
+
10
+ ```javascript
11
+ // First run: builds cache
12
+ await testdriver.find('submit button');
13
+
14
+ // Second run: exact match
15
+ await testdriver.find('submit button');
16
+ ```
17
+
18
+ ## Automatic Caching
19
+
20
+ Caching is enabled automatically with zero configuration. The cache key is computed from:
21
+
22
+ - **File hash**: SHA-256 hash of the test file contents
23
+ - **Selector prompt**: The exact text description passed to `find()`
24
+ - **Screenshot context**: Perceptual hash of the current screen state
25
+ - **Platform**: Operating system and browser version
26
+
27
+ When you modify your test file, the hash changes automatically, invalidating stale cache entries and ensuring fresh AI analysis with your updated test logic.
28
+
29
+ ```javascript
30
+ import { test } from 'vitest';
31
+ import { chrome } from 'testdriverai/presets';
32
+
33
+ test('auto-cached test', async (context) => {
34
+ const { testdriver } = await chrome(context, {
35
+ url: 'https://example.com'
36
+ });
37
+
38
+ // First call: AI analyzes screen, saves to cache
39
+ await testdriver.find('More information link'); // 2.1s
40
+
41
+ // Second call: cache hit, instant response
42
+ await testdriver.find('More information link'); // 12ms ⚡
43
+ });
44
+ ```
45
+
46
+ ## Managing the Cache
47
+
48
+ You can clear the cache within the TestDriver console. There, you'll also find previews of cached elements, the input prompts, as well as analytics on cache hit rates.
49
+
50
+ <Card href="https://console.testdriver.ai/cache" title="TestDriver Cache" icon="database">
51
+ Manage and clear your test cache from the TestDriver console.
52
+ </Card>
53
+
54
+ ## Debugging Cache Hits and Misses
55
+
56
+ You can track cache performance in your tests:
57
+
58
+ ```javascript
59
+ test('monitor cache performance', async (context) => {
60
+ const { testdriver } = await chrome(context, { url });
61
+
62
+ const element = await testdriver.find('submit button');
63
+
64
+ if (element.cacheHit) {
65
+ console.log('✅ Cache hit - instant response');
66
+ console.log('Strategy:', element.cacheStrategy); // 'exact', 'pixeldiff', or 'template'
67
+ console.log('Similarity:', `${(element.similarity * 100).toFixed(1)}%`);
68
+ console.log('Cache age:', element.cacheCreatedAt);
69
+ } else {
70
+ console.log('⏱️ Cache miss - AI analysis performed');
71
+ console.log('New cache entry created');
72
+ }
73
+ });
74
+ ```
75
+
76
+ ## Configuring the Cache
77
+
78
+ You can configure cache behavior globally when initializing TestDriver:
79
+
80
+ ```javascript
81
+ import { TestDriver } from 'testdriverai';
82
+
83
+ const testdriver = new TestDriver({
84
+ apiKey: process.env.TD_API_KEY,
85
+ cacheKey: 'my-test-suite', // cache-key for this instance
86
+ cacheDefaults: {
87
+ threshold: 0.05, // 95% similarity
88
+ }
89
+ });
90
+ ```
91
+
92
+ It's also possible to override cache settings per `find()` call:
93
+
94
+ ```javascript
95
+ // Default: 95% similarity required
96
+ await testdriver.find('submit button');
97
+
98
+ // Explicit strict threshold
99
+ await testdriver.find('submit button', {
100
+ cacheThreshold: 0.01 // 99% similarity
101
+ });
102
+ ```
103
+
104
+ ## Caching with Variables
105
+
106
+ Custom cache keys prevent cache pollution when using variables in prompts, dramatically improving cache hit rates.
107
+
108
+ ```javascript
109
+ // ❌ Without cache key - creates new cache for each variable value
110
+ const email = 'user@example.com';
111
+ await testdriver.find(`input for ${email}`); // Cache miss every time
112
+
113
+ // ✅ With cache key - reuses cache regardless of variable
114
+ const email = 'user@example.com';
115
+ await testdriver.find(`input for ${email}`, {
116
+ cacheKey: 'email-input'
117
+ });
118
+
119
+ // Also useful for dynamic IDs, names, or other changing data
120
+ const orderId = generateOrderId();
121
+ await testdriver.find(`order ${orderId} status`, {
122
+ cacheKey: 'order-status' // Same cache for all orders
123
+ });
124
+ ```