testdriverai 7.1.0 → 7.1.2
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/.env.example +2 -0
- package/.github/workflows/linux-tests.yml +28 -0
- package/agent/index.js +18 -45
- package/agent/interface.js +13 -2
- package/agent/lib/commands.js +1 -1
- package/agent/lib/redraw.js +1 -1
- package/agent/lib/sandbox.js +30 -2
- package/agent/lib/valid-version.js +2 -2
- package/debugger/index.html +1 -1
- package/docs/docs.json +140 -131
- package/docs/v6/getting-started/self-hosting.mdx +3 -2
- package/docs/v7/_drafts/agents.mdx +852 -0
- package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
- package/docs/v7/{guides → _drafts}/caching-selectors.mdx +125 -17
- package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
- package/docs/v7/_drafts/error-handling.mdx +501 -0
- package/docs/v7/_drafts/implementation-plan.mdx +994 -0
- package/docs/v7/_drafts/init-command.mdx +95 -0
- package/docs/v7/_drafts/optimal-sdk-design.mdx +1348 -0
- package/docs/v7/_drafts/plugin-migration.mdx +222 -0
- package/docs/v7/_drafts/prompt-cache.mdx +200 -0
- package/docs/{QUICK_START_TEST_RECORDING.md → v7/_drafts/quick-start-test-recording.mdx} +3 -3
- package/docs/v7/_drafts/sdk-logging.mdx +222 -0
- package/docs/v7/_drafts/sdk-migration.mdx +474 -0
- package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
- package/docs/v7/{guides → _drafts}/self-hosting.mdx +1 -1
- package/docs/v7/{guides → _drafts}/troubleshooting.mdx +2 -2
- package/docs/v7/{guides → _drafts}/vitest-plugin.mdx +4 -4
- package/docs/v7/api/{ai.mdx → act.mdx} +24 -24
- package/docs/v7/api/client.mdx +1 -1
- package/docs/v7/api/dashcam.mdx +2 -2
- package/docs/v7/api/elements.mdx +143 -41
- package/docs/v7/api/find.mdx +258 -0
- package/docs/v7/api/type.mdx +51 -7
- package/docs/v7/features/ai-native.mdx +427 -0
- package/docs/v7/features/easy-to-write.mdx +351 -0
- package/docs/v7/features/enterprise.mdx +540 -0
- package/docs/v7/features/fast.mdx +424 -0
- package/docs/v7/features/observable.mdx +623 -0
- package/docs/v7/features/powerful.mdx +531 -0
- package/docs/v7/features/scalable.mdx +417 -0
- package/docs/v7/features/stable.mdx +514 -0
- package/docs/v7/getting-started/configuration.mdx +1 -1
- package/docs/v7/getting-started/generating-tests.mdx +525 -0
- package/docs/v7/getting-started/installation.mdx +486 -0
- package/docs/v7/getting-started/quickstart.mdx +51 -5
- package/docs/v7/getting-started/running-and-debugging.mdx +511 -0
- package/docs/v7/getting-started/setting-up-in-ci.mdx +612 -0
- package/docs/v7/getting-started/writing-tests.mdx +535 -0
- package/docs/v7/overview/what-is-testdriver.mdx +398 -0
- package/docs/v7/playwright.mdx +3 -3
- package/docs/v7/presets/chrome.mdx +16 -0
- package/docs/v7/presets/electron.mdx +18 -0
- package/docs/v7/presets/vscode.mdx +19 -0
- package/examples/run-tests-with-recording.sh +70 -0
- package/examples/screenshot-example.js +63 -0
- package/examples/sdk-awesome-logs-demo.js +177 -0
- package/examples/sdk-cache-thresholds.js +96 -0
- package/examples/sdk-element-properties.js +155 -0
- package/examples/sdk-simple-example.js +65 -0
- package/examples/test-recording-example.test.js +166 -0
- package/interfaces/cli/commands/init.js +358 -0
- package/interfaces/vitest-plugin.mjs +214 -10
- package/{src → lib}/core/Dashcam.js +41 -4
- package/{src → lib}/vitest/hooks.mjs +118 -100
- package/lib/vitest/setup.mjs +44 -0
- package/package.json +9 -10
- package/sdk.d.ts +15 -2
- package/sdk.js +72 -17
- package/{self-hosted.yml → setup/aws/self-hosted.yml} +1 -1
- package/{testdriver/acceptance-sdk → test/manual}/test-console-logs.test.mjs +1 -1
- package/test/manual/test-find-api.js +73 -0
- package/test/manual/test-init.sh +54 -0
- package/test/manual/test-prompt-cache.js +96 -0
- package/test/manual/test-provision-auth.mjs +22 -0
- package/test/manual/test-sandbox-render.js +28 -0
- package/test/manual/test-sdk-methods.js +15 -0
- package/test/manual/test-sdk-refactor.js +53 -0
- package/test/manual/test-stack-trace.mjs +57 -0
- package/test/testdriver/assert.test.mjs +41 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/auto-cache-key-demo.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/drag-and-drop.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/element-not-found.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-js.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-output.test.mjs +3 -3
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-pwsh.test.mjs +3 -3
- package/{testdriver/acceptance-sdk → test/testdriver}/focus-window.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/formatted-logging.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text-with-description.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/match-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/press-keys.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/prompt.test.mjs +2 -2
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-keyboard.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-text.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll.test.mjs +1 -1
- package/{src/vitest/lifecycle.mjs → test/testdriver/setup/lifecycleHelpers.mjs} +84 -99
- package/test/testdriver/setup/testHelpers.mjs +653 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/type.test.mjs +1 -1
- package/vitest.config.mjs +8 -59
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/acceptance-linux.yml +0 -75
- package/.github/workflows/acceptance-sdk-tests.yml +0 -133
- package/.github/workflows/acceptance-tests.yml +0 -130
- package/.github/workflows/lint.yml +0 -27
- package/.github/workflows/publish-canary.yml +0 -40
- package/.github/workflows/publish-latest.yml +0 -61
- package/.github/workflows/test-install.yml +0 -29
- package/.vscode/extensions.json +0 -3
- package/.vscode/launch.json +0 -22
- package/.vscode/settings.json +0 -14
- package/AGENTS.md +0 -550
- package/CODEOWNERS +0 -2
- package/_testdriver/acceptance/assert.yaml +0 -7
- package/_testdriver/acceptance/dashcam.yaml +0 -9
- package/_testdriver/acceptance/drag-and-drop.yaml +0 -49
- package/_testdriver/acceptance/embed.yaml +0 -9
- package/_testdriver/acceptance/exec-js.yaml +0 -29
- package/_testdriver/acceptance/exec-output.yaml +0 -43
- package/_testdriver/acceptance/exec-shell.yaml +0 -40
- package/_testdriver/acceptance/focus-window.yaml +0 -16
- package/_testdriver/acceptance/hover-image.yaml +0 -18
- package/_testdriver/acceptance/hover-text-with-description.yaml +0 -29
- package/_testdriver/acceptance/hover-text.yaml +0 -14
- package/_testdriver/acceptance/if-else.yaml +0 -31
- package/_testdriver/acceptance/match-image.yaml +0 -15
- package/_testdriver/acceptance/press-keys.yaml +0 -35
- package/_testdriver/acceptance/prompt.yaml +0 -11
- package/_testdriver/acceptance/remember.yaml +0 -27
- package/_testdriver/acceptance/screenshots/cart.png +0 -0
- package/_testdriver/acceptance/scroll-keyboard.yaml +0 -34
- package/_testdriver/acceptance/scroll-until-image.yaml +0 -26
- package/_testdriver/acceptance/scroll-until-text.yaml +0 -20
- package/_testdriver/acceptance/scroll.yaml +0 -33
- package/_testdriver/acceptance/snippets/login.yaml +0 -29
- package/_testdriver/acceptance/snippets/match-cart.yaml +0 -8
- package/_testdriver/acceptance/type.yaml +0 -29
- package/_testdriver/behavior/failure.yaml +0 -7
- package/_testdriver/behavior/hover-text.yaml +0 -13
- package/_testdriver/behavior/lifecycle/postrun.yaml +0 -10
- package/_testdriver/behavior/lifecycle/prerun.yaml +0 -8
- package/_testdriver/behavior/lifecycle/provision.yaml +0 -8
- package/_testdriver/behavior/secrets.yaml +0 -7
- package/_testdriver/edge-cases/dashcam-chrome.yaml +0 -8
- package/_testdriver/edge-cases/exec-pwsh-multiline.yaml +0 -10
- package/_testdriver/edge-cases/js-exception.yaml +0 -8
- package/_testdriver/edge-cases/js-promise.yaml +0 -19
- package/_testdriver/edge-cases/lifecycle/postrun.yaml +0 -10
- package/_testdriver/edge-cases/prompt-in-middle.yaml +0 -23
- package/_testdriver/edge-cases/prompt-nested.yaml +0 -7
- package/_testdriver/edge-cases/success-test.yaml +0 -9
- package/_testdriver/examples/android/example.yaml +0 -12
- package/_testdriver/examples/android/lifecycle/postrun.yaml +0 -11
- package/_testdriver/examples/android/lifecycle/provision.yaml +0 -47
- package/_testdriver/examples/android/readme.md +0 -7
- package/_testdriver/examples/chrome-extension/lifecycle/provision.yaml +0 -74
- package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
- package/_testdriver/examples/desktop/lifecycle/provision.yaml +0 -64
- package/_testdriver/examples/vscode-extension/lifecycle/provision.yaml +0 -73
- package/_testdriver/examples/web/lifecycle/postrun.yaml +0 -7
- package/_testdriver/examples/web/lifecycle/prerun.yaml +0 -22
- package/_testdriver/lifecycle/postrun.yaml +0 -8
- package/_testdriver/lifecycle/prerun.yaml +0 -15
- package/_testdriver/lifecycle/provision.yaml +0 -25
- package/docs/v7/guides/ci-cd/azure.mdx +0 -587
- package/docs/v7/guides/ci-cd/circleci.mdx +0 -523
- package/docs/v7/guides/ci-cd/github-actions.mdx +0 -457
- package/docs/v7/guides/ci-cd/gitlab.mdx +0 -498
- package/docs/v7/guides/ci-cd/jenkins.mdx +0 -664
- package/docs/v7/guides/ci-cd/travis.mdx +0 -438
- package/scripts/view-test-results.mjs +0 -96
- package/src/vitest/extended.mjs +0 -108
- package/src/vitest/index.mjs +0 -64
- package/src/vitest/utils.mjs +0 -150
- package/styles/.vale-config/2-MDX.ini +0 -5
- package/styles/Microsoft/AMPM.yml +0 -9
- package/styles/Microsoft/Accessibility.yml +0 -30
- package/styles/Microsoft/Acronyms.yml +0 -64
- package/styles/Microsoft/Adverbs.yml +0 -272
- package/styles/Microsoft/Auto.yml +0 -11
- package/styles/Microsoft/Avoid.yml +0 -14
- package/styles/Microsoft/Contractions.yml +0 -50
- package/styles/Microsoft/Dashes.yml +0 -13
- package/styles/Microsoft/DateFormat.yml +0 -8
- package/styles/Microsoft/DateNumbers.yml +0 -40
- package/styles/Microsoft/DateOrder.yml +0 -8
- package/styles/Microsoft/Ellipses.yml +0 -9
- package/styles/Microsoft/FirstPerson.yml +0 -16
- package/styles/Microsoft/Foreign.yml +0 -13
- package/styles/Microsoft/Gender.yml +0 -8
- package/styles/Microsoft/GenderBias.yml +0 -42
- package/styles/Microsoft/GeneralURL.yml +0 -11
- package/styles/Microsoft/HeadingAcronyms.yml +0 -7
- package/styles/Microsoft/HeadingColons.yml +0 -8
- package/styles/Microsoft/HeadingPunctuation.yml +0 -13
- package/styles/Microsoft/Headings.yml +0 -28
- package/styles/Microsoft/Hyphens.yml +0 -14
- package/styles/Microsoft/Negative.yml +0 -13
- package/styles/Microsoft/Ordinal.yml +0 -13
- package/styles/Microsoft/OxfordComma.yml +0 -8
- package/styles/Microsoft/Passive.yml +0 -183
- package/styles/Microsoft/Percentages.yml +0 -7
- package/styles/Microsoft/Plurals.yml +0 -7
- package/styles/Microsoft/Quotes.yml +0 -7
- package/styles/Microsoft/RangeTime.yml +0 -13
- package/styles/Microsoft/Semicolon.yml +0 -8
- package/styles/Microsoft/SentenceLength.yml +0 -6
- package/styles/Microsoft/Spacing.yml +0 -8
- package/styles/Microsoft/Suspended.yml +0 -7
- package/styles/Microsoft/Terms.yml +0 -42
- package/styles/Microsoft/URLFormat.yml +0 -9
- package/styles/Microsoft/Units.yml +0 -16
- package/styles/Microsoft/Vocab.yml +0 -25
- package/styles/Microsoft/We.yml +0 -11
- package/styles/Microsoft/Wordiness.yml +0 -127
- package/styles/Microsoft/meta.json +0 -4
- package/styles/alex/Ablist.yml +0 -274
- package/styles/alex/Condescending.yml +0 -16
- package/styles/alex/Gendered.yml +0 -110
- package/styles/alex/LGBTQ.yml +0 -55
- package/styles/alex/OCD.yml +0 -10
- package/styles/alex/Press.yml +0 -12
- package/styles/alex/ProfanityLikely.yml +0 -1289
- package/styles/alex/ProfanityMaybe.yml +0 -282
- package/styles/alex/ProfanityUnlikely.yml +0 -251
- package/styles/alex/README.md +0 -27
- package/styles/alex/Race.yml +0 -85
- package/styles/alex/Suicide.yml +0 -26
- package/styles/alex/meta.json +0 -4
- package/styles/config/vocabularies/Docs/accept.txt +0 -47
- package/styles/config/vocabularies/Docs/reject.txt +0 -4
- package/styles/proselint/Airlinese.yml +0 -8
- package/styles/proselint/AnimalLabels.yml +0 -48
- package/styles/proselint/Annotations.yml +0 -9
- package/styles/proselint/Apologizing.yml +0 -8
- package/styles/proselint/Archaisms.yml +0 -52
- package/styles/proselint/But.yml +0 -8
- package/styles/proselint/Cliches.yml +0 -782
- package/styles/proselint/CorporateSpeak.yml +0 -30
- package/styles/proselint/Currency.yml +0 -5
- package/styles/proselint/Cursing.yml +0 -15
- package/styles/proselint/DateCase.yml +0 -7
- package/styles/proselint/DateMidnight.yml +0 -7
- package/styles/proselint/DateRedundancy.yml +0 -10
- package/styles/proselint/DateSpacing.yml +0 -7
- package/styles/proselint/DenizenLabels.yml +0 -52
- package/styles/proselint/Diacritical.yml +0 -95
- package/styles/proselint/GenderBias.yml +0 -45
- package/styles/proselint/GroupTerms.yml +0 -39
- package/styles/proselint/Hedging.yml +0 -8
- package/styles/proselint/Hyperbole.yml +0 -6
- package/styles/proselint/Jargon.yml +0 -11
- package/styles/proselint/LGBTOffensive.yml +0 -13
- package/styles/proselint/LGBTTerms.yml +0 -15
- package/styles/proselint/Malapropisms.yml +0 -8
- package/styles/proselint/Needless.yml +0 -358
- package/styles/proselint/Nonwords.yml +0 -38
- package/styles/proselint/Oxymorons.yml +0 -22
- package/styles/proselint/P-Value.yml +0 -6
- package/styles/proselint/RASSyndrome.yml +0 -30
- package/styles/proselint/README.md +0 -12
- package/styles/proselint/Skunked.yml +0 -13
- package/styles/proselint/Spelling.yml +0 -17
- package/styles/proselint/Typography.yml +0 -11
- package/styles/proselint/Uncomparables.yml +0 -50
- package/styles/proselint/Very.yml +0 -6
- package/styles/proselint/meta.json +0 -15
- package/styles/write-good/Cliches.yml +0 -702
- package/styles/write-good/E-Prime.yml +0 -32
- package/styles/write-good/Illusions.yml +0 -11
- package/styles/write-good/Passive.yml +0 -183
- package/styles/write-good/README.md +0 -27
- package/styles/write-good/So.yml +0 -5
- package/styles/write-good/ThereIs.yml +0 -6
- package/styles/write-good/TooWordy.yml +0 -221
- package/styles/write-good/Weasel.yml +0 -29
- package/styles/write-good/meta.json +0 -4
- package/test/dashcam.test.js +0 -137
- package/test/mcp-example-test.yaml +0 -27
- package/test/test_parser.js +0 -47
- package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +0 -61
- package/testdriver/acceptance-sdk/README.md +0 -128
- package/testdriver/acceptance-sdk/TEST_REPORTING.md +0 -245
- package/testdriver/acceptance-sdk/assert.test.mjs +0 -26
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +0 -38
- package/testdriver/acceptance-sdk/presets-example.test.mjs +0 -87
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +0 -420
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +0 -234
- package/testdriver/acceptance-sdk/type-checking-demo.js +0 -49
- package/vale.ini +0 -18
- package/vitest.config.example.js +0 -19
- package/vitest.config.mjs.bak +0 -44
- /package/docs/{ARCHITECTURE.md → v7/_drafts/architecture.mdx} +0 -0
- /package/docs/{AWESOME_LOGS_QUICK_REF.md → v7/_drafts/awesome-logs-quick-ref.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/best-practices.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/caching-ai.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/caching.mdx +0 -0
- /package/docs/{MIGRATION.md → v7/_drafts/cli-to-sdk-migration.mdx} +0 -0
- /package/{CONTRIBUTING.md → docs/v7/_drafts/contributing.mdx} +0 -0
- /package/docs/v7/{progressive-apis/CORE.md → _drafts/core.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/debugging.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/faq.mdx +0 -0
- /package/docs/v7/{progressive-apis/HOOKS.md → _drafts/hooks.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/migration.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/performance.mdx +0 -0
- /package/docs/{PRESETS.md → v7/_drafts/presets.mdx} +0 -0
- /package/docs/v7/{progressive-apis/PROGRESSIVE_DISCLOSURE.md → _drafts/progressive-disclosure.mdx} +0 -0
- /package/docs/v7/{progressive-apis/PROVISION.md → _drafts/provision.mdx} +0 -0
- /package/docs/{SDK_AWESOME_LOGS.md → v7/_drafts/sdk-awesome-logs.mdx} +0 -0
- /package/docs/{sdk-browser-rendering.md → v7/_drafts/sdk-browser-rendering.mdx} +0 -0
- /package/docs/{TEST_RECORDING.md → v7/_drafts/test-recording.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/vitest.mdx +0 -0
- /package/docs/v7/{README.md → overview/readme.mdx} +0 -0
- /package/{src → lib}/core/index.d.ts +0 -0
- /package/{src → lib}/core/index.js +0 -0
- /package/{src → lib}/presets/index.mjs +0 -0
- /package/{src → lib}/vitest/hooks.d.ts +0 -0
- /package/{debug-locate-response.js → test/manual/debug-locate-response.js} +0 -0
- /package/{verify-element-api.js → test/manual/verify-element-api.js} +0 -0
- /package/{verify-types.js → test/manual/verify-types.js} +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/chrome-extension.test.mjs +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/setup/globalTeardown.mjs +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/setup/vitestSetup.mjs +0 -0
package/AGENTS.md
DELETED
|
@@ -1,550 +0,0 @@
|
|
|
1
|
-
# TestDriver Agent Instructions
|
|
2
|
-
|
|
3
|
-
This guide teaches AI agents how to write modular, iteratively-debuggable Vitest tests using the TestDriver SDK.
|
|
4
|
-
|
|
5
|
-
## Core Principles
|
|
6
|
-
|
|
7
|
-
### 1. One Action Per Step
|
|
8
|
-
|
|
9
|
-
Each `it()` block performs exactly **ONE state-changing action** plus optional assertions.
|
|
10
|
-
|
|
11
|
-
**State-changing actions:**
|
|
12
|
-
- `click()` - clicking on elements
|
|
13
|
-
- `type()` - typing text
|
|
14
|
-
- `pressKeys()` - keyboard shortcuts
|
|
15
|
-
- `scroll()` - scrolling the page
|
|
16
|
-
|
|
17
|
-
**NOT state-changing (can combine with actions):**
|
|
18
|
-
- `find()` - locating elements
|
|
19
|
-
- `assert()` - verifying state
|
|
20
|
-
- `exists()` - checking element presence
|
|
21
|
-
- `screenshot()` - capturing screen
|
|
22
|
-
|
|
23
|
-
```javascript
|
|
24
|
-
// ✅ CORRECT: One action per step
|
|
25
|
-
it("step01: click the login button", async () => {
|
|
26
|
-
const button = await testdriver.find("Login button");
|
|
27
|
-
await button.click();
|
|
28
|
-
// Optional: verify the action worked
|
|
29
|
-
const form = await testdriver.find("Login form");
|
|
30
|
-
expect(form.exists()).toBe(true);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("step02: type username", async () => {
|
|
34
|
-
await testdriver.type("testuser");
|
|
35
|
-
await testdriver.assert("username field contains 'testuser'");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// ❌ WRONG: Multiple actions in one step
|
|
39
|
-
it("login flow", async () => {
|
|
40
|
-
await testdriver.find("Login").click();
|
|
41
|
-
await testdriver.type("user"); // second action!
|
|
42
|
-
await testdriver.type("password"); // third action!
|
|
43
|
-
await testdriver.find("Submit").click(); // fourth action!
|
|
44
|
-
});
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 2. Step Naming Convention
|
|
48
|
-
|
|
49
|
-
Use zero-padded step numbers for proper sorting and easy `--testNamePattern` filtering:
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
it("step01: open application", async () => { ... });
|
|
53
|
-
it("step02: click login button", async () => { ... });
|
|
54
|
-
it("step03: enter username", async () => { ... });
|
|
55
|
-
it("step04: enter password", async () => { ... });
|
|
56
|
-
it("step05: submit form", async () => { ... });
|
|
57
|
-
it("step06: verify dashboard loaded", async () => { ... });
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 3. All Steps in One File
|
|
61
|
-
|
|
62
|
-
Write all steps for a test flow in the same file. This allows:
|
|
63
|
-
- Running the entire flow: `vitest path/to/test.test.js`
|
|
64
|
-
- Debugging a single step: `vitest --testNamePattern "step03"`
|
|
65
|
-
|
|
66
|
-
### 4. Optional Assertions
|
|
67
|
-
|
|
68
|
-
Assertions verify the action worked. Use them when appropriate:
|
|
69
|
-
|
|
70
|
-
```javascript
|
|
71
|
-
// After clicking - verify navigation or state change
|
|
72
|
-
it("step01: click submit button", async () => {
|
|
73
|
-
await testdriver.find("Submit button").click();
|
|
74
|
-
await testdriver.assert("form was submitted successfully");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// After typing - verify text appeared (optional, typing is deterministic)
|
|
78
|
-
it("step02: type search query", async () => {
|
|
79
|
-
await testdriver.type("search term");
|
|
80
|
-
// assertion optional for typing
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Use exists() for element presence
|
|
84
|
-
it("step03: verify modal appeared", async () => {
|
|
85
|
-
const modal = await testdriver.find("Confirmation modal");
|
|
86
|
-
expect(modal.exists()).toBe(true);
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
## Test Structure
|
|
91
|
-
|
|
92
|
-
### Basic Template
|
|
93
|
-
|
|
94
|
-
```javascript
|
|
95
|
-
import { describe, it, expect } from "vitest";
|
|
96
|
-
import { TestDriver } from "testdriverai/vitest";
|
|
97
|
-
|
|
98
|
-
describe("Feature Name", () => {
|
|
99
|
-
it("step01: provision and first action", async (context) => {
|
|
100
|
-
const testdriver = TestDriver(context);
|
|
101
|
-
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
102
|
-
|
|
103
|
-
// First action + optional assertion
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("step02: second action", async (context) => {
|
|
107
|
-
const testdriver = TestDriver(context);
|
|
108
|
-
|
|
109
|
-
// action + optional assertion
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Key Points:**
|
|
115
|
-
- Each test gets its own `testdriver` via `TestDriver(context)`
|
|
116
|
-
- Call `provision.chrome({ url })` in the first step to launch the browser
|
|
117
|
-
- Subsequent steps don't need to provision - the sandbox persists
|
|
118
|
-
|
|
119
|
-
## Shared Helpers
|
|
120
|
-
|
|
121
|
-
### Reusing Common Flows
|
|
122
|
-
|
|
123
|
-
Before writing steps for common flows (login, navigation, setup), check if a helper already exists.
|
|
124
|
-
|
|
125
|
-
**Helper Location:** `testdriver/helpers/`
|
|
126
|
-
|
|
127
|
-
### Creating a Helper
|
|
128
|
-
|
|
129
|
-
```javascript
|
|
130
|
-
// testdriver/helpers/login.js
|
|
131
|
-
export async function login(testdriver, username = "testuser", password = "password") {
|
|
132
|
-
const loginButton = await testdriver.find("Login button");
|
|
133
|
-
await loginButton.click();
|
|
134
|
-
|
|
135
|
-
await testdriver.type(username);
|
|
136
|
-
await testdriver.pressKeys(["Tab"]);
|
|
137
|
-
await testdriver.type(password);
|
|
138
|
-
|
|
139
|
-
const submitButton = await testdriver.find("Submit button");
|
|
140
|
-
await submitButton.click();
|
|
141
|
-
|
|
142
|
-
await testdriver.assert("user is logged in");
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Using a Helper
|
|
147
|
-
|
|
148
|
-
```javascript
|
|
149
|
-
import { describe, it, expect } from "vitest";
|
|
150
|
-
import { TestDriver } from "testdriverai/vitest";
|
|
151
|
-
import { login } from "./helpers/login.js";
|
|
152
|
-
|
|
153
|
-
describe("Dashboard Tests", () => {
|
|
154
|
-
it("step01: provision and login", async (context) => {
|
|
155
|
-
const testdriver = TestDriver(context);
|
|
156
|
-
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
157
|
-
await login(testdriver);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("step02: navigate to settings", async (context) => {
|
|
161
|
-
const testdriver = TestDriver(context);
|
|
162
|
-
const settingsLink = await testdriver.find("Settings link in sidebar");
|
|
163
|
-
await settingsLink.click();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// ... more steps
|
|
167
|
-
});
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### When to Create Helpers
|
|
171
|
-
|
|
172
|
-
Create a helper when:
|
|
173
|
-
- Flow is used in multiple tests (login, logout, navigation)
|
|
174
|
-
- Flow has 3+ steps that are always done together
|
|
175
|
-
- Flow requires specific credentials or configuration
|
|
176
|
-
|
|
177
|
-
## Iterative Development Workflow
|
|
178
|
-
|
|
179
|
-
**CRITICAL: Write and run tests ONE STEP AT A TIME.** Do not write the entire test file upfront. Build it incrementally.
|
|
180
|
-
|
|
181
|
-
### The Loop
|
|
182
|
-
|
|
183
|
-
```
|
|
184
|
-
┌─────────────────────────────────────────────────────────┐
|
|
185
|
-
│ 1. Write ONE step │
|
|
186
|
-
│ 2. Run that step: vitest --testNamePattern "stepNN" │
|
|
187
|
-
│ 3. Did it pass? │
|
|
188
|
-
│ ├─ YES → Go to step 1, write next step │
|
|
189
|
-
│ └─ NO → Fix the step, go to step 2 │
|
|
190
|
-
│ 4. When all steps pass, run entire file │
|
|
191
|
-
└─────────────────────────────────────────────────────────┘
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Detailed Workflow
|
|
195
|
-
|
|
196
|
-
#### Phase 1: Setup the Test File
|
|
197
|
-
|
|
198
|
-
Create the file with the describe block and NO steps yet:
|
|
199
|
-
|
|
200
|
-
```javascript
|
|
201
|
-
import { describe, it, expect } from "vitest";
|
|
202
|
-
import { TestDriver } from "testdriverai/vitest";
|
|
203
|
-
|
|
204
|
-
describe("My Feature Test", () => {
|
|
205
|
-
// Steps will be added one at a time below
|
|
206
|
-
});
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
#### Phase 2: Write Step 1
|
|
210
|
-
|
|
211
|
-
Add the first step with provisioning:
|
|
212
|
-
|
|
213
|
-
```javascript
|
|
214
|
-
it("step01: open app and click login", async (context) => {
|
|
215
|
-
const testdriver = TestDriver(context);
|
|
216
|
-
await testdriver.provision.chrome({ url: 'https://example.com/login' });
|
|
217
|
-
|
|
218
|
-
const button = await testdriver.find("Login button in the header");
|
|
219
|
-
await button.click();
|
|
220
|
-
});
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
#### Phase 3: Run Step 1
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
vitest --testNamePattern "step01" path/to/test.test.js
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
**If it passes:** Move to Phase 4.
|
|
230
|
-
|
|
231
|
-
**If it fails:**
|
|
232
|
-
- Check the error message
|
|
233
|
-
- Take a screenshot to see actual screen state
|
|
234
|
-
- Common fixes:
|
|
235
|
-
- Improve the `find()` description (be more specific)
|
|
236
|
-
- The element might not be visible yet (add scroll or wait)
|
|
237
|
-
- Wrong element clicked (check coordinates)
|
|
238
|
-
- Edit the step and re-run the same command
|
|
239
|
-
|
|
240
|
-
#### Phase 4: Write Step 2
|
|
241
|
-
|
|
242
|
-
Only after step 1 passes, add step 2:
|
|
243
|
-
|
|
244
|
-
```javascript
|
|
245
|
-
it("step02: type username", async (context) => {
|
|
246
|
-
const testdriver = TestDriver(context);
|
|
247
|
-
await testdriver.type("testuser");
|
|
248
|
-
});
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
#### Phase 5: Run Step 2
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
vitest --testNamePattern "step02" path/to/test.test.js
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
The sandbox persists from step 1, so the app is already in the right state.
|
|
258
|
-
|
|
259
|
-
**If it passes:** Continue to step 3.
|
|
260
|
-
|
|
261
|
-
**If it fails:** Fix and re-run step 2 only.
|
|
262
|
-
|
|
263
|
-
#### Phase 6: Repeat
|
|
264
|
-
|
|
265
|
-
Continue this pattern:
|
|
266
|
-
1. Write step N
|
|
267
|
-
2. Run step N
|
|
268
|
-
3. Fix until passing
|
|
269
|
-
4. Write step N+1
|
|
270
|
-
|
|
271
|
-
#### Phase 7: Run Full Test
|
|
272
|
-
|
|
273
|
-
When all steps pass individually:
|
|
274
|
-
|
|
275
|
-
```bash
|
|
276
|
-
vitest path/to/test.test.js
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
This runs all steps in sequence to verify the complete flow.
|
|
280
|
-
|
|
281
|
-
### Why One Step at a Time?
|
|
282
|
-
|
|
283
|
-
1. **Faster debugging** - If step 5 fails, you only re-run step 5, not steps 1-4
|
|
284
|
-
2. **Sandbox reuse** - The sandbox persists, so previous steps don't need to re-run
|
|
285
|
-
3. **Immediate feedback** - You see if each action works before moving on
|
|
286
|
-
4. **Easier fixes** - Smaller changes are easier to debug
|
|
287
|
-
|
|
288
|
-
### Example: Building a Test Incrementally
|
|
289
|
-
|
|
290
|
-
**Goal:** Test user login
|
|
291
|
-
|
|
292
|
-
**Iteration 1:** Write and run step01
|
|
293
|
-
```javascript
|
|
294
|
-
it("step01: provision and click login", async (context) => {
|
|
295
|
-
const testdriver = TestDriver(context);
|
|
296
|
-
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
297
|
-
|
|
298
|
-
const button = await testdriver.find("Login button");
|
|
299
|
-
await button.click();
|
|
300
|
-
});
|
|
301
|
-
```
|
|
302
|
-
```bash
|
|
303
|
-
vitest --testNamePattern "step01" login.test.js
|
|
304
|
-
# ✅ Passed
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
**Iteration 2:** Write and run step02
|
|
308
|
-
```javascript
|
|
309
|
-
it("step02: type username", async (context) => {
|
|
310
|
-
const testdriver = TestDriver(context);
|
|
311
|
-
await testdriver.type("admin");
|
|
312
|
-
});
|
|
313
|
-
```
|
|
314
|
-
```bash
|
|
315
|
-
vitest --testNamePattern "step02" login.test.js
|
|
316
|
-
# ❌ Failed - typing into wrong field
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
**Iteration 2b:** Fix step02 - need to click the field first
|
|
320
|
-
```javascript
|
|
321
|
-
it("step02: click username field", async (context) => {
|
|
322
|
-
const testdriver = TestDriver(context);
|
|
323
|
-
const field = await testdriver.find("Username input field");
|
|
324
|
-
await field.click();
|
|
325
|
-
});
|
|
326
|
-
```
|
|
327
|
-
```bash
|
|
328
|
-
vitest --testNamePattern "step02" login.test.js
|
|
329
|
-
# ✅ Passed
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
**Iteration 3:** Write and run step03
|
|
333
|
-
```javascript
|
|
334
|
-
it("step03: type username", async (context) => {
|
|
335
|
-
const testdriver = TestDriver(context);
|
|
336
|
-
await testdriver.type("admin");
|
|
337
|
-
});
|
|
338
|
-
```
|
|
339
|
-
```bash
|
|
340
|
-
vitest --testNamePattern "step03" login.test.js
|
|
341
|
-
# ✅ Passed
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
Continue until complete...
|
|
345
|
-
|
|
346
|
-
## Sandbox Persistence
|
|
347
|
-
|
|
348
|
-
TestDriver automatically persists sandbox connections:
|
|
349
|
-
|
|
350
|
-
- **Project-local:** `.testdriver-sandbox.json` in current directory
|
|
351
|
-
- **Timeout:** 10 minutes of inactivity
|
|
352
|
-
- **Auto-reconnect:** Automatically reuses recent sandbox on next run
|
|
353
|
-
|
|
354
|
-
During development:
|
|
355
|
-
- Don't call `disconnect()` in `afterAll`
|
|
356
|
-
- Sandbox stays alive between test runs
|
|
357
|
-
- If sandbox expires, a new one is created automatically
|
|
358
|
-
|
|
359
|
-
### One-Time Setup Steps
|
|
360
|
-
|
|
361
|
-
Use `it.once()` for steps that should only run once per sandbox session (app launch, provisioning):
|
|
362
|
-
|
|
363
|
-
```javascript
|
|
364
|
-
import { describe, it, beforeAll, expect } from "testdriverai/vitest";
|
|
365
|
-
import TestDriver from "testdriverai";
|
|
366
|
-
|
|
367
|
-
describe("My Test", () => {
|
|
368
|
-
let testdriver;
|
|
369
|
-
|
|
370
|
-
beforeAll(async () => {
|
|
371
|
-
testdriver = new TestDriver(process.env.TD_API_KEY);
|
|
372
|
-
await testdriver.connect();
|
|
373
|
-
|
|
374
|
-
// Store globally so it.once() can check isReconnected
|
|
375
|
-
globalThis.__testdriver = testdriver;
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
// Only runs once per sandbox session - skipped on reconnect
|
|
379
|
-
it.once("launch the application", async () => {
|
|
380
|
-
await testdriver.exec("sh", "google-chrome https://example.com", 5000);
|
|
381
|
-
await testdriver.assert("application is loaded");
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// Always runs
|
|
385
|
-
it("click the login button", async () => {
|
|
386
|
-
const button = await testdriver.find("Login button");
|
|
387
|
-
await button.click();
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
// Always runs
|
|
391
|
-
it("type username", async () => {
|
|
392
|
-
await testdriver.type("testuser");
|
|
393
|
-
});
|
|
394
|
-
});
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
**When to use `it.once()`:**
|
|
398
|
-
- Launching the application
|
|
399
|
-
- Navigating to initial URL
|
|
400
|
-
- One-time provisioning steps
|
|
401
|
-
- Any step that sets up state that persists in the sandbox
|
|
402
|
-
|
|
403
|
-
**Regular `it()` steps:**
|
|
404
|
-
- All subsequent actions
|
|
405
|
-
- Steps you're actively developing/debugging
|
|
406
|
-
|
|
407
|
-
This lets you run the full file and one-time steps are automatically skipped on reconnect:
|
|
408
|
-
```bash
|
|
409
|
-
# First run: setup runs, then all steps
|
|
410
|
-
vitest path/to/test.test.js
|
|
411
|
-
|
|
412
|
-
# Second run (within 10 min): setup skipped, runs from first regular step
|
|
413
|
-
vitest path/to/test.test.js
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
**How it works:**
|
|
417
|
-
- The SDK sets `testdriver.isReconnected = true` when it reconnects to an existing sandbox
|
|
418
|
-
- `it.once()` checks `globalThis.__testdriver.isReconnected` to decide whether to skip
|
|
419
|
-
|
|
420
|
-
## SDK Quick Reference
|
|
421
|
-
|
|
422
|
-
### Finding Elements
|
|
423
|
-
|
|
424
|
-
```javascript
|
|
425
|
-
// Find returns an Element with coordinates
|
|
426
|
-
const element = await testdriver.find("description of element");
|
|
427
|
-
|
|
428
|
-
// Chain directly
|
|
429
|
-
await testdriver.find("Submit button").click();
|
|
430
|
-
|
|
431
|
-
// Check if found
|
|
432
|
-
if (element.exists()) { ... }
|
|
433
|
-
|
|
434
|
-
// Get coordinates
|
|
435
|
-
const { x, y, centerX, centerY } = element.getCoordinates();
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### Actions
|
|
439
|
-
|
|
440
|
-
```javascript
|
|
441
|
-
// Click (on found element)
|
|
442
|
-
await element.click();
|
|
443
|
-
await element.click("double-click");
|
|
444
|
-
await element.click("right-click");
|
|
445
|
-
|
|
446
|
-
// Type text (into focused field)
|
|
447
|
-
await testdriver.type("text to type");
|
|
448
|
-
await testdriver.type("text", 100); // with delay between keys
|
|
449
|
-
|
|
450
|
-
// Keyboard shortcuts
|
|
451
|
-
await testdriver.pressKeys(["ctrl", "c"]);
|
|
452
|
-
await testdriver.pressKeys(["cmd", "shift", "p"]);
|
|
453
|
-
|
|
454
|
-
// Scroll
|
|
455
|
-
await testdriver.scroll("down", 300);
|
|
456
|
-
await testdriver.scroll("up", 500, "keyboard");
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### Verification
|
|
460
|
-
|
|
461
|
-
```javascript
|
|
462
|
-
// AI-powered assertion (flexible, visual)
|
|
463
|
-
const passed = await testdriver.assert("the form was submitted successfully");
|
|
464
|
-
expect(passed).toBe(true);
|
|
465
|
-
|
|
466
|
-
// Element existence
|
|
467
|
-
const element = await testdriver.find("Success message");
|
|
468
|
-
expect(element.exists()).toBe(true);
|
|
469
|
-
|
|
470
|
-
// Screenshot for debugging
|
|
471
|
-
const screenshot = await testdriver.screenshot();
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Remember (Extract Values)
|
|
475
|
-
|
|
476
|
-
```javascript
|
|
477
|
-
// Extract dynamic values from screen
|
|
478
|
-
const orderNumber = await testdriver.remember("the order confirmation number");
|
|
479
|
-
console.log("Order:", orderNumber);
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
## Example: Complete Test File
|
|
483
|
-
|
|
484
|
-
```javascript
|
|
485
|
-
import { describe, it, expect } from "vitest";
|
|
486
|
-
import { TestDriver } from "testdriverai/vitest";
|
|
487
|
-
|
|
488
|
-
describe("User Registration", () => {
|
|
489
|
-
it("step01: provision and navigate to registration", async (context) => {
|
|
490
|
-
const testdriver = TestDriver(context);
|
|
491
|
-
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
492
|
-
|
|
493
|
-
const signupLink = await testdriver.find("Sign Up link in navigation");
|
|
494
|
-
await signupLink.click();
|
|
495
|
-
await testdriver.assert("registration form is visible");
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
it("step02: enter email address", async (context) => {
|
|
499
|
-
const testdriver = TestDriver(context);
|
|
500
|
-
const emailField = await testdriver.find("Email input field");
|
|
501
|
-
await emailField.click();
|
|
502
|
-
await testdriver.type("test@example.com");
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
it("step03: enter password", async (context) => {
|
|
506
|
-
const testdriver = TestDriver(context);
|
|
507
|
-
const passwordField = await testdriver.find("Password input field");
|
|
508
|
-
await passwordField.click();
|
|
509
|
-
await testdriver.type("SecurePass123!");
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
it("step04: confirm password", async (context) => {
|
|
513
|
-
const testdriver = TestDriver(context);
|
|
514
|
-
const confirmField = await testdriver.find("Confirm password field");
|
|
515
|
-
await confirmField.click();
|
|
516
|
-
await testdriver.type("SecurePass123!");
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it("step05: accept terms and conditions", async (context) => {
|
|
520
|
-
const testdriver = TestDriver(context);
|
|
521
|
-
const checkbox = await testdriver.find("Terms and conditions checkbox");
|
|
522
|
-
await checkbox.click();
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it("step06: submit registration", async (context) => {
|
|
526
|
-
const testdriver = TestDriver(context);
|
|
527
|
-
const submitButton = await testdriver.find("Create Account button");
|
|
528
|
-
await submitButton.click();
|
|
529
|
-
await testdriver.assert("account was created successfully");
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
it("step07: verify welcome message", async (context) => {
|
|
533
|
-
const testdriver = TestDriver(context);
|
|
534
|
-
const welcome = await testdriver.find("Welcome message");
|
|
535
|
-
expect(welcome.exists()).toBe(true);
|
|
536
|
-
});
|
|
537
|
-
});
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
## Tips for AI Agents
|
|
541
|
-
|
|
542
|
-
1. **Write ONE step at a time** - Never write the full test upfront. Write step 1, run it, fix it, then write step 2.
|
|
543
|
-
2. **Run after each step** - Use `vitest --testNamePattern "stepNN"` to test each step immediately
|
|
544
|
-
3. **Search before writing** - Check `testdriver/helpers/` for existing flows
|
|
545
|
-
4. **Descriptive find()** - Include location, color, text: "blue Submit button below the form"
|
|
546
|
-
5. **One action at a time** - Easier to debug when things fail
|
|
547
|
-
6. **Assert after important actions** - Especially navigation and form submissions
|
|
548
|
-
7. **Use step numbers** - Makes `--testNamePattern` filtering easy
|
|
549
|
-
8. **Don't disconnect during dev** - Let sandbox persist for faster iteration
|
|
550
|
-
9. **Check screenshots** - When steps fail, look at actual screen state
|
package/CODEOWNERS
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# yaml-language-server: $schema=https://raw.githubusercontent.com/testdriverai/cli/refs/heads/main/schema.json
|
|
2
|
-
|
|
3
|
-
version: 6.0.5
|
|
4
|
-
session: 687aa621328371880ec75e89
|
|
5
|
-
steps:
|
|
6
|
-
- prompt: Show the desktop
|
|
7
|
-
commands:
|
|
8
|
-
- command: press-keys
|
|
9
|
-
keys:
|
|
10
|
-
- win
|
|
11
|
-
- d
|
|
12
|
-
- prompt: Open the context menu
|
|
13
|
-
commands:
|
|
14
|
-
- command: press-keys
|
|
15
|
-
keys:
|
|
16
|
-
- shift
|
|
17
|
-
- f10
|
|
18
|
-
- prompt: Hover over "New" in the context menu
|
|
19
|
-
commands:
|
|
20
|
-
- command: hover-text
|
|
21
|
-
text: New
|
|
22
|
-
description: new option in the open context menu on the desktop
|
|
23
|
-
action: hover
|
|
24
|
-
- prompt: Click "Text Document" in the context menu
|
|
25
|
-
commands:
|
|
26
|
-
- command: hover-text
|
|
27
|
-
text: Text Document
|
|
28
|
-
description: text document option in the new submenu of the desktop context menu
|
|
29
|
-
action: click
|
|
30
|
-
- prompt: Unfocus the "Text Document" text field
|
|
31
|
-
commands:
|
|
32
|
-
- command: press-keys
|
|
33
|
-
keys:
|
|
34
|
-
- esc
|
|
35
|
-
- prompt: Drag the "New Text Document" icon to the "Recycle Bin"
|
|
36
|
-
commands:
|
|
37
|
-
- command: hover-text
|
|
38
|
-
text: New Text Document
|
|
39
|
-
description: new text document icon in the center of the desktop
|
|
40
|
-
action: mouseDown
|
|
41
|
-
- command: hover-text
|
|
42
|
-
text: Recycle Bin
|
|
43
|
-
description: recycle bin icon in the top left corner of the desktop
|
|
44
|
-
action: mouseUp
|
|
45
|
-
|
|
46
|
-
- prompt: '"New Text Document" icon is not on the Desktop'
|
|
47
|
-
commands:
|
|
48
|
-
- command: assert
|
|
49
|
-
expect: the "New Text Document" icon is not visible on the Desktop
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
version: 5.7.7
|
|
2
|
-
session: 682f5fc22856e2eb40664269
|
|
3
|
-
steps:
|
|
4
|
-
- prompt: fetch user data from API
|
|
5
|
-
commands:
|
|
6
|
-
- command: exec
|
|
7
|
-
output: user
|
|
8
|
-
lang: js
|
|
9
|
-
code: >
|
|
10
|
-
const response = await
|
|
11
|
-
fetch('https://jsonplaceholder.typicode.com/users');
|
|
12
|
-
|
|
13
|
-
const user = await response.json();
|
|
14
|
-
|
|
15
|
-
console.log('user', user[0]);
|
|
16
|
-
|
|
17
|
-
result = user[0].email;
|
|
18
|
-
- command: hover-text
|
|
19
|
-
text: Username
|
|
20
|
-
description: input field for username
|
|
21
|
-
action: click
|
|
22
|
-
- command: type
|
|
23
|
-
text: ${OUTPUT.user}
|
|
24
|
-
- prompt: assert that the username field shows a valid email address
|
|
25
|
-
commands:
|
|
26
|
-
- command: assert
|
|
27
|
-
expect: >-
|
|
28
|
-
the username field contains "Sincere@april.biz" which is a valid email
|
|
29
|
-
address
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
version: 6.0.1-canary.dd4927e.0
|
|
2
|
-
session: 686f219f56143a3ffe789d1e
|
|
3
|
-
steps:
|
|
4
|
-
- prompt: set the date for our test
|
|
5
|
-
commands:
|
|
6
|
-
- command: exec
|
|
7
|
-
lang: pwsh
|
|
8
|
-
output: queryString
|
|
9
|
-
code: |
|
|
10
|
-
$date = (Get-Date).AddMonths(1)
|
|
11
|
-
Write-Output $date.ToString("yyyy-MM-dd")
|
|
12
|
-
- command: assert
|
|
13
|
-
expect: ${OUTPUT.queryString} is a valid date
|
|
14
|
-
- prompt: set the date for our assertion
|
|
15
|
-
commands:
|
|
16
|
-
- command: exec
|
|
17
|
-
lang: pwsh
|
|
18
|
-
output: expectedDate
|
|
19
|
-
code: |
|
|
20
|
-
$date = (Get-Date).AddMonths(1)
|
|
21
|
-
Write-Output $date.ToString("ddd MMM d yyyy")
|
|
22
|
-
# Go to a public calendar that accepts query strings to set the date
|
|
23
|
-
- prompt: >-
|
|
24
|
-
now press ctrl + l, then type
|
|
25
|
-
https://teamup.com/ks48cf2135e7e080bc?view=d&date=${OUTPUT.queryString} and press enter
|
|
26
|
-
commands:
|
|
27
|
-
- command: focus-application
|
|
28
|
-
name: Google Chrome
|
|
29
|
-
- command: press-keys
|
|
30
|
-
keys:
|
|
31
|
-
- ctrl
|
|
32
|
-
- l
|
|
33
|
-
- command: type
|
|
34
|
-
text: https://teamup.com/ks48cf2135e7e080bc?view=d&date=${OUTPUT.queryString}
|
|
35
|
-
- command: press-keys
|
|
36
|
-
keys:
|
|
37
|
-
- enter
|
|
38
|
-
- prompt: assert that the date ${OUTPUT.expectedDate} shows
|
|
39
|
-
commands:
|
|
40
|
-
- command: focus-application
|
|
41
|
-
name: Google Chrome
|
|
42
|
-
- command: assert
|
|
43
|
-
expect: the text ${OUTPUT.expectedDate} is visible on screen
|