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
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Repo-Specific Test Helpers
|
|
3
|
-
*
|
|
4
|
-
* These helpers are specific to this repository's test infrastructure.
|
|
5
|
-
* For reusable plugin helpers, import from 'testdriverai/vitest' (or src/vitest/index.mjs locally)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import crypto from "crypto";
|
|
9
|
-
import { config } from "dotenv";
|
|
10
|
-
import fs from "fs";
|
|
11
|
-
import os from "os";
|
|
12
|
-
import path, { dirname } from "path";
|
|
13
|
-
import { fileURLToPath } from "url";
|
|
14
|
-
|
|
15
|
-
// Import TestDriver SDK locally (for repo development)
|
|
16
|
-
import TestDriver from "../../../sdk.js";
|
|
17
|
-
|
|
18
|
-
// Import plugin helpers
|
|
19
|
-
import {
|
|
20
|
-
addDashcamLog,
|
|
21
|
-
authDashcam,
|
|
22
|
-
launchChrome,
|
|
23
|
-
launchChromeExtension,
|
|
24
|
-
launchChromeForTesting,
|
|
25
|
-
runPostrun,
|
|
26
|
-
runPrerun,
|
|
27
|
-
runPrerunChromeExtension,
|
|
28
|
-
runPrerunChromeForTesting,
|
|
29
|
-
startDashcam,
|
|
30
|
-
stopDashcam,
|
|
31
|
-
waitForPage,
|
|
32
|
-
} from "../../../src/vitest/lifecycle.mjs";
|
|
33
|
-
|
|
34
|
-
import {
|
|
35
|
-
retryAsync,
|
|
36
|
-
setupEventLogging,
|
|
37
|
-
sleep,
|
|
38
|
-
waitFor,
|
|
39
|
-
} from "../../../src/vitest/utils.mjs";
|
|
40
|
-
|
|
41
|
-
// Re-export plugin lifecycle helpers for backward compatibility
|
|
42
|
-
export {
|
|
43
|
-
addDashcamLog,
|
|
44
|
-
authDashcam,
|
|
45
|
-
launchChrome,
|
|
46
|
-
launchChromeExtension,
|
|
47
|
-
launchChromeForTesting,
|
|
48
|
-
runPostrun,
|
|
49
|
-
runPrerun,
|
|
50
|
-
runPrerunChromeExtension,
|
|
51
|
-
runPrerunChromeForTesting,
|
|
52
|
-
startDashcam,
|
|
53
|
-
stopDashcam,
|
|
54
|
-
waitForPage
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Re-export plugin utilities for backward compatibility
|
|
58
|
-
export {
|
|
59
|
-
retryAsync,
|
|
60
|
-
setupEventLogging,
|
|
61
|
-
sleep,
|
|
62
|
-
waitFor
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// Get the directory of the current module
|
|
66
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
67
|
-
const __dirname = dirname(__filename);
|
|
68
|
-
|
|
69
|
-
// Load environment variables from .env file in the project root
|
|
70
|
-
const envPath = path.resolve(__dirname, "../../../.env");
|
|
71
|
-
config({ path: envPath });
|
|
72
|
-
|
|
73
|
-
// Log loaded env vars for debugging
|
|
74
|
-
console.log("🔧 Environment variables loaded from:", envPath);
|
|
75
|
-
console.log(" TD_API_KEY:", process.env.TD_API_KEY ? "✓ Set" : "✗ Not set");
|
|
76
|
-
console.log(" TD_API_ROOT:", process.env.TD_API_ROOT || "Not set");
|
|
77
|
-
console.log(" TD_OS:", process.env.TD_OS || "Not set (will default to linux)");
|
|
78
|
-
|
|
79
|
-
// =============================================================================
|
|
80
|
-
// TEST RESULTS STORAGE (Repo-specific CI/CD integration)
|
|
81
|
-
// =============================================================================
|
|
82
|
-
|
|
83
|
-
const testResults = {
|
|
84
|
-
tests: [],
|
|
85
|
-
startTime: Date.now(),
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Store test result with dashcam URL
|
|
90
|
-
* @param {string} testName - Name of the test
|
|
91
|
-
* @param {string} testFile - Test file path
|
|
92
|
-
* @param {string|null} dashcamUrl - Dashcam URL if available
|
|
93
|
-
* @param {Object} sessionInfo - Session information
|
|
94
|
-
*/
|
|
95
|
-
export function storeTestResult(testName, testFile, dashcamUrl, sessionInfo = {}) {
|
|
96
|
-
console.log(`📝 Storing test result: ${testName}`);
|
|
97
|
-
console.log(` Dashcam URL: ${dashcamUrl || "none"}`);
|
|
98
|
-
|
|
99
|
-
let replayObjectId = null;
|
|
100
|
-
if (dashcamUrl) {
|
|
101
|
-
const replayIdMatch = dashcamUrl.match(/\/replay\/([^?]+)/);
|
|
102
|
-
replayObjectId = replayIdMatch ? replayIdMatch[1] : null;
|
|
103
|
-
if (replayObjectId) {
|
|
104
|
-
console.log(` Replay Object ID: ${replayObjectId}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
testResults.tests.push({
|
|
109
|
-
name: testName,
|
|
110
|
-
file: testFile,
|
|
111
|
-
dashcamUrl,
|
|
112
|
-
replayObjectId,
|
|
113
|
-
sessionId: sessionInfo.sessionId,
|
|
114
|
-
timestamp: new Date().toISOString(),
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Get all test results
|
|
120
|
-
* @returns {Object} All collected test results
|
|
121
|
-
*/
|
|
122
|
-
export function getTestResults() {
|
|
123
|
-
return {
|
|
124
|
-
...testResults,
|
|
125
|
-
endTime: Date.now(),
|
|
126
|
-
duration: Date.now() - testResults.startTime,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Save test results to a JSON file
|
|
132
|
-
* @param {string} outputPath - Path to save the results
|
|
133
|
-
*/
|
|
134
|
-
export function saveTestResults(outputPath = "test-results/sdk-summary.json") {
|
|
135
|
-
const results = getTestResults();
|
|
136
|
-
const dir = path.dirname(outputPath);
|
|
137
|
-
|
|
138
|
-
if (!fs.existsSync(dir)) {
|
|
139
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
fs.writeFileSync(outputPath, JSON.stringify(results, null, 2));
|
|
143
|
-
console.log(`\n📊 Test results saved to: ${outputPath}`);
|
|
144
|
-
|
|
145
|
-
console.log("\n🎥 Dashcam URLs:");
|
|
146
|
-
results.tests.forEach((test) => {
|
|
147
|
-
if (test.dashcamUrl) {
|
|
148
|
-
console.log(` ${test.name}: ${test.dashcamUrl}`);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
return results;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// =============================================================================
|
|
156
|
-
// REPO-SPECIFIC CLIENT CREATION
|
|
157
|
-
// =============================================================================
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Create a configured TestDriver client for this repo's tests
|
|
161
|
-
* Uses local SDK path for development
|
|
162
|
-
* @param {Object} options - Additional options
|
|
163
|
-
* @returns {TestDriver} Configured client
|
|
164
|
-
*/
|
|
165
|
-
export function createTestClient(options = {}) {
|
|
166
|
-
if (!process.env.TD_API_KEY) {
|
|
167
|
-
console.error("\n❌ Error: TD_API_KEY is not set!");
|
|
168
|
-
console.error("Please set it in one of the following ways:");
|
|
169
|
-
console.error(" 1. Create a .env file in the project root with: TD_API_KEY=your_key");
|
|
170
|
-
console.error(" 2. Pass it as an environment variable: TD_API_KEY=your_key npm run test:sdk");
|
|
171
|
-
console.error(" 3. Export it in your shell: export TD_API_KEY=your_key\n");
|
|
172
|
-
throw new Error("TD_API_KEY environment variable is required");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const osConfig = process.env.TEST_PLATFORM || "linux";
|
|
176
|
-
const { task, ...clientOptions } = options;
|
|
177
|
-
const taskId = task?.id || task?.name || null;
|
|
178
|
-
|
|
179
|
-
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
180
|
-
resolution: "1366x768",
|
|
181
|
-
analytics: true,
|
|
182
|
-
os: osConfig,
|
|
183
|
-
apiKey: process.env.TD_API_KEY,
|
|
184
|
-
apiRoot: process.env.TD_API_ROOT || "https://testdriver-api.onrender.com",
|
|
185
|
-
newSandbox: true,
|
|
186
|
-
...clientOptions,
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
console.log("🔧 createTestClient: SDK created, cacheThresholds =", client.cacheThresholds);
|
|
190
|
-
console.log(`[TestHelpers] Client OS configured as: ${client.os}`);
|
|
191
|
-
|
|
192
|
-
if (taskId) {
|
|
193
|
-
console.log(`[TestHelpers] Storing task ID on client: ${taskId}`);
|
|
194
|
-
client.vitestTaskId = taskId;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (process.env.DEBUG_EVENTS === "true") {
|
|
198
|
-
setupEventLogging(client);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return client;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// =============================================================================
|
|
205
|
-
// REPO-SPECIFIC LOGIN HELPER (for TestDriver Sandbox)
|
|
206
|
-
// =============================================================================
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Perform login flow on TestDriver Sandbox
|
|
210
|
-
* This is specific to http://testdriver-sandbox.vercel.app/login
|
|
211
|
-
* @param {TestDriver} client - TestDriver client
|
|
212
|
-
* @param {string} username - Username (default: 'standard_user')
|
|
213
|
-
* @param {string} password - Password (default: retrieved from screen)
|
|
214
|
-
*/
|
|
215
|
-
export async function performLogin(client, username = "standard_user", password = null) {
|
|
216
|
-
await client.focusApplication("Google Chrome");
|
|
217
|
-
|
|
218
|
-
if (!password) {
|
|
219
|
-
password = await client.remember("the password");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const usernameField = await client.find(
|
|
223
|
-
"Username, label above the username input field on the login form",
|
|
224
|
-
);
|
|
225
|
-
await usernameField.click();
|
|
226
|
-
await client.type(username);
|
|
227
|
-
|
|
228
|
-
await client.pressKeys(["tab"]);
|
|
229
|
-
await client.type(password, { secret: true });
|
|
230
|
-
|
|
231
|
-
await client.pressKeys(["tab"]);
|
|
232
|
-
await client.pressKeys(["enter"]);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// =============================================================================
|
|
236
|
-
// SUITE TEST RUN MANAGEMENT (CI/CD Integration)
|
|
237
|
-
// =============================================================================
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Initialize a test run for the entire suite
|
|
241
|
-
* @param {Object} suiteTask - Vitest suite task context
|
|
242
|
-
* @returns {Promise<Object>} Test run info { runId, testRunDbId, token }
|
|
243
|
-
*/
|
|
244
|
-
export async function initializeSuiteTestRun(suiteTask) {
|
|
245
|
-
const apiKey = process.env.TD_API_KEY;
|
|
246
|
-
const apiRoot = process.env.TD_API_ROOT || "https://testdriver-api.onrender.com";
|
|
247
|
-
|
|
248
|
-
if (!apiKey || !globalThis.__testdriverPlugin) {
|
|
249
|
-
console.log(`[TestHelpers] Skipping suite test run initialization - no API key or plugin`);
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const existingRun = globalThis.__testdriverPlugin.getSuiteTestRun(suiteTask.id);
|
|
254
|
-
if (existingRun) {
|
|
255
|
-
console.log(`[TestHelpers] Test run already exists for suite: ${existingRun.runId}`);
|
|
256
|
-
return existingRun;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
try {
|
|
260
|
-
console.log(`[TestHelpers] Initializing test run for suite: ${suiteTask.name}`);
|
|
261
|
-
|
|
262
|
-
const token = await globalThis.__testdriverPlugin.authenticateWithApiKey(apiKey, apiRoot);
|
|
263
|
-
console.log(`[TestHelpers] ✅ Authenticated for suite`);
|
|
264
|
-
|
|
265
|
-
const runId = `${Date.now()}-${crypto.randomBytes(4).toString("hex")}`;
|
|
266
|
-
const testFile = suiteTask.file?.name || "unknown";
|
|
267
|
-
const testRunData = {
|
|
268
|
-
runId,
|
|
269
|
-
suiteName: suiteTask.name || testFile,
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const testRunResponse = await globalThis.__testdriverPlugin.createTestRunDirect(
|
|
273
|
-
token,
|
|
274
|
-
apiRoot,
|
|
275
|
-
testRunData,
|
|
276
|
-
);
|
|
277
|
-
const testRunDbId = testRunResponse.data?.id;
|
|
278
|
-
|
|
279
|
-
const runInfo = { runId, testRunDbId, token };
|
|
280
|
-
globalThis.__testdriverPlugin.setSuiteTestRun(suiteTask.id, runInfo);
|
|
281
|
-
|
|
282
|
-
process.env.TD_TEST_RUN_ID = runId;
|
|
283
|
-
process.env.TD_TEST_RUN_DB_ID = testRunDbId;
|
|
284
|
-
process.env.TD_TEST_RUN_TOKEN = token;
|
|
285
|
-
|
|
286
|
-
console.log(`[TestHelpers] ✅ Created test run for suite: ${runId} (DB ID: ${testRunDbId})`);
|
|
287
|
-
return runInfo;
|
|
288
|
-
} catch (error) {
|
|
289
|
-
console.error(`[TestHelpers] ❌ Failed to initialize suite test run:`, error.message);
|
|
290
|
-
return null;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// =============================================================================
|
|
295
|
-
// SETUP/TEARDOWN HELPERS
|
|
296
|
-
// =============================================================================
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Setup function to run before each test
|
|
300
|
-
* @param {TestDriver} client - TestDriver client
|
|
301
|
-
* @param {Object} options - Connection options
|
|
302
|
-
* @returns {Promise<Object>} Sandbox instance
|
|
303
|
-
*/
|
|
304
|
-
export async function setupTest(client, options = {}) {
|
|
305
|
-
await client.auth();
|
|
306
|
-
const instance = await client.connect({ ...options });
|
|
307
|
-
|
|
308
|
-
if (options.prerun !== false) {
|
|
309
|
-
await runPrerun(client);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return instance;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Teardown function to run after each test
|
|
317
|
-
* @param {TestDriver} client - TestDriver client
|
|
318
|
-
* @param {Object} options - Teardown options
|
|
319
|
-
* @returns {Promise<Object>} Session info including dashcam URL
|
|
320
|
-
*/
|
|
321
|
-
export async function teardownTest(client, options = {}) {
|
|
322
|
-
let dashcamUrl = options.dashcamUrl || null;
|
|
323
|
-
|
|
324
|
-
console.log("🧹 Running teardown...");
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
if (options.postrun !== false && !dashcamUrl) {
|
|
328
|
-
dashcamUrl = await runPostrun(client);
|
|
329
|
-
|
|
330
|
-
if (dashcamUrl && options.task) {
|
|
331
|
-
const replayIdMatch = dashcamUrl.match(/\/replay\/([^?]+)/);
|
|
332
|
-
const replayObjectId = replayIdMatch ? replayIdMatch[1] : null;
|
|
333
|
-
|
|
334
|
-
console.log(`🎥 Dashcam URL: ${dashcamUrl}`);
|
|
335
|
-
if (replayObjectId) {
|
|
336
|
-
console.log(`📝 Replay Object ID: ${replayObjectId}`);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
options.task.meta.testdriverDashcamUrl = dashcamUrl;
|
|
340
|
-
options.task.meta.testdriverReplayObjectId = replayObjectId;
|
|
341
|
-
console.log(`[TestHelpers] ✅ Stored dashcam URL in task.meta for test: ${options.task.name}`);
|
|
342
|
-
}
|
|
343
|
-
} else {
|
|
344
|
-
console.log("⏭️ Postrun skipped (disabled in options)");
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Write test result to temp file for reporter
|
|
348
|
-
if (options.task) {
|
|
349
|
-
const testResultFile = path.join(
|
|
350
|
-
os.tmpdir(),
|
|
351
|
-
"testdriver-results",
|
|
352
|
-
`${options.task.id}.json`,
|
|
353
|
-
);
|
|
354
|
-
|
|
355
|
-
try {
|
|
356
|
-
const dir = path.dirname(testResultFile);
|
|
357
|
-
if (!fs.existsSync(dir)) {
|
|
358
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const testFile = options.task.file?.filepath || options.task.file?.name || "unknown";
|
|
362
|
-
let testOrder = 0;
|
|
363
|
-
if (options.task.suite && options.task.suite.tasks) {
|
|
364
|
-
testOrder = options.task.suite.tasks.indexOf(options.task);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const result = options.task.result?.();
|
|
368
|
-
const duration = result?.duration || 0;
|
|
369
|
-
|
|
370
|
-
const testResult = {
|
|
371
|
-
testId: options.task.id,
|
|
372
|
-
testName: options.task.name,
|
|
373
|
-
testFile: testFile,
|
|
374
|
-
testOrder: testOrder,
|
|
375
|
-
dashcamUrl: dashcamUrl,
|
|
376
|
-
replayObjectId: dashcamUrl ? dashcamUrl.match(/\/replay\/([^?]+)/)?.[1] : null,
|
|
377
|
-
platform: client.os,
|
|
378
|
-
timestamp: Date.now(),
|
|
379
|
-
duration: duration,
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
fs.writeFileSync(testResultFile, JSON.stringify(testResult, null, 2));
|
|
383
|
-
console.log(`[TestHelpers] ✅ Wrote test result to file: ${testResultFile}`);
|
|
384
|
-
} catch (error) {
|
|
385
|
-
console.error(`[TestHelpers] ❌ Failed to write test result file:`, error.message);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
} catch (error) {
|
|
389
|
-
console.error("❌ Error in postrun:", error);
|
|
390
|
-
console.error("❌ Error stack:", error.stack);
|
|
391
|
-
} finally {
|
|
392
|
-
if (options.disconnect !== false) {
|
|
393
|
-
console.log("🔌 Disconnecting client...");
|
|
394
|
-
try {
|
|
395
|
-
await client.disconnect();
|
|
396
|
-
console.log("✅ Client disconnected");
|
|
397
|
-
} catch (disconnectError) {
|
|
398
|
-
console.error("❌ Error disconnecting:", disconnectError.message);
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
console.log("⏭️ Disconnect skipped (disabled in options)");
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
let replayObjectId = null;
|
|
406
|
-
if (dashcamUrl) {
|
|
407
|
-
const replayIdMatch = dashcamUrl.match(/\/replay\/([^?]+)/);
|
|
408
|
-
replayObjectId = replayIdMatch ? replayIdMatch[1] : null;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const sessionInfo = {
|
|
412
|
-
sessionId: client.getSessionId(),
|
|
413
|
-
dashcamUrl: dashcamUrl,
|
|
414
|
-
replayObjectId: replayObjectId,
|
|
415
|
-
instance: client.getInstance(),
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
console.log("📊 Session info:", JSON.stringify(sessionInfo, null, 2));
|
|
419
|
-
return sessionInfo;
|
|
420
|
-
}
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { chrome } from "../../src/presets/index.mjs";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* CHECKPOINT SYSTEM GUIDE FOR TESTDRIVER TESTS
|
|
6
|
-
* ============================================
|
|
7
|
-
*
|
|
8
|
-
* When newSandbox is set to false in chrome(), the sandbox persists between test runs.
|
|
9
|
-
* This allows you to skip completed steps when debugging or developing tests.
|
|
10
|
-
*
|
|
11
|
-
* HOW TO USE CHECKPOINTS:
|
|
12
|
-
*
|
|
13
|
-
* 1. Run your test normally until it fails at a certain step
|
|
14
|
-
* 2. Find the checkpoint comment just before the failing section (e.g., "// CHECKPOINT: Login Complete")
|
|
15
|
-
* 3. Comment out all code BEFORE that checkpoint using /* ... *\/ block comments
|
|
16
|
-
* 4. Re-run the test - it will resume from that checkpoint using the existing sandbox state
|
|
17
|
-
* 5. Once the test passes completely, uncomment all sections to verify end-to-end
|
|
18
|
-
*
|
|
19
|
-
* CHECKPOINT LOCATIONS IN THIS TEST:
|
|
20
|
-
* - CHECKPOINT 1: Cookie banner handled
|
|
21
|
-
* - CHECKPOINT 2: Login complete
|
|
22
|
-
* - CHECKPOINT 3: Patients page loaded
|
|
23
|
-
* - CHECKPOINT 4: Patient selected/created
|
|
24
|
-
* - CHECKPOINT 5: Patient profile opened
|
|
25
|
-
*
|
|
26
|
-
* IMPORTANT: Always set newSandbox: false in chrome() options to enable this feature!
|
|
27
|
-
*
|
|
28
|
-
* FOR AI ASSISTANTS:
|
|
29
|
-
* When helping users debug TestDriver tests:
|
|
30
|
-
* - If a test fails at a certain step, suggest commenting out earlier checkpoints
|
|
31
|
-
* - Remind them to set newSandbox: false
|
|
32
|
-
* - After fixes, remind them to uncomment all code for full end-to-end validation
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
// Helper function to poll for an element until it's found
|
|
36
|
-
async function waitForElement(testdriver, description, maxAttempts = 10, delayMs = 1000) {
|
|
37
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
38
|
-
try {
|
|
39
|
-
const element = await testdriver.find(description);
|
|
40
|
-
if (element.found()) {
|
|
41
|
-
return element;
|
|
42
|
-
}
|
|
43
|
-
} catch (e) {
|
|
44
|
-
if (i === maxAttempts - 1) throw e;
|
|
45
|
-
}
|
|
46
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
47
|
-
}
|
|
48
|
-
throw new Error(`Element not found after ${maxAttempts} attempts: ${description}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe("Sully.ai Patient Management Workflow", () => {
|
|
52
|
-
it("should complete full patient workflow: login, view patients, update note, and edit profile", async (context) => {
|
|
53
|
-
const { testdriver } = await chrome(context, {
|
|
54
|
-
url: 'https://app.sully.ai',
|
|
55
|
-
redrawThreshold: { enabled: true }
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// ========================================================================
|
|
59
|
-
// CHECKPOINT 1: Cookie Banner
|
|
60
|
-
// If test fails after this point, comment out this section (lines above)
|
|
61
|
-
// ========================================================================
|
|
62
|
-
|
|
63
|
-
// Handle cookie banner if present
|
|
64
|
-
try {
|
|
65
|
-
const acceptCookies = await testdriver.find("Accept All button for cookies");
|
|
66
|
-
await acceptCookies.click();
|
|
67
|
-
} catch {
|
|
68
|
-
console.log("No cookie banner or already dismissed");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Wait for login page to load by polling for email field
|
|
72
|
-
console.log("Waiting for login page to load...");
|
|
73
|
-
const emailField = await waitForElement(testdriver, "Email input field");
|
|
74
|
-
console.log("Found email field");
|
|
75
|
-
await emailField.click();
|
|
76
|
-
await testdriver.type("razeen+testdriver@sully.ai");
|
|
77
|
-
|
|
78
|
-
const passwordField = await testdriver.find("Password input field");
|
|
79
|
-
await passwordField.click();
|
|
80
|
-
await testdriver.type("plmokn7@A", {secret: true});
|
|
81
|
-
|
|
82
|
-
const loginButton = await testdriver.find("Login button");
|
|
83
|
-
await loginButton.click();
|
|
84
|
-
|
|
85
|
-
// ========================================================================
|
|
86
|
-
// CHECKPOINT 2: Login Complete
|
|
87
|
-
// If test fails after this point, comment out all code above this checkpoint
|
|
88
|
-
// ========================================================================
|
|
89
|
-
|
|
90
|
-
// Wait for navigation to complete after login
|
|
91
|
-
console.log("Waiting for login to process...");
|
|
92
|
-
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
93
|
-
|
|
94
|
-
// Take a screenshot to see where we are
|
|
95
|
-
await testdriver.screenshot();
|
|
96
|
-
console.log("Screenshot taken after login");
|
|
97
|
-
|
|
98
|
-
// Verify login successful
|
|
99
|
-
const loginSuccess = await testdriver.assert("user is logged in and on the main application page or dashboard");
|
|
100
|
-
expect(loginSuccess).toBeTruthy();
|
|
101
|
-
|
|
102
|
-
// Poll for dashboard element to ensure login completed
|
|
103
|
-
console.log("Looking for Patients link...");
|
|
104
|
-
await waitForElement(testdriver, "Patients button or link in the navigation menu", 15, 1000);
|
|
105
|
-
|
|
106
|
-
// Dismiss password save dialog first if it appears
|
|
107
|
-
try {
|
|
108
|
-
const neverButton = await testdriver.find("Never button or Never save button");
|
|
109
|
-
await neverButton.click();
|
|
110
|
-
console.log("Dismissed password save dialog");
|
|
111
|
-
} catch {
|
|
112
|
-
console.log("Password save dialog not found");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
await testdriver.find("save profile changes popup or banner").click();
|
|
116
|
-
|
|
117
|
-
// Click Patients
|
|
118
|
-
const patientsLink = await testdriver.find("Patients navigation link or menu item");
|
|
119
|
-
await patientsLink.click();
|
|
120
|
-
|
|
121
|
-
// ========================================================================
|
|
122
|
-
// CHECKPOINT 3: Patients Page Loaded
|
|
123
|
-
// If test fails after this point, comment out all code above this checkpoint
|
|
124
|
-
// ========================================================================
|
|
125
|
-
|
|
126
|
-
// Approach 1: Search for existing patient
|
|
127
|
-
const existingPatientInput = await testdriver.find("Patient search input box");
|
|
128
|
-
await existingPatientInput.click();
|
|
129
|
-
|
|
130
|
-
// Type a search term to find a patient
|
|
131
|
-
await testdriver.type("Patient Test");
|
|
132
|
-
|
|
133
|
-
// Poll for search results to appear
|
|
134
|
-
const firstPatient = await waitForElement(testdriver, "first patient name in the dropdown or list", 5, 500);
|
|
135
|
-
await firstPatient.click();
|
|
136
|
-
|
|
137
|
-
console.log("Found patient via search");
|
|
138
|
-
|
|
139
|
-
// Verify patient visit page or details are loaded
|
|
140
|
-
const patientLoaded = await testdriver.assert("we are on a patient recording page");
|
|
141
|
-
expect(patientLoaded).toBeTruthy();
|
|
142
|
-
|
|
143
|
-
// ========================================================================
|
|
144
|
-
// CHECKPOINT 4: Patient Selected/Created
|
|
145
|
-
// If test fails after this point, comment out all code above this checkpoint
|
|
146
|
-
// ========================================================================
|
|
147
|
-
|
|
148
|
-
await testdriver.find('input box at the bottom of the screen').click();
|
|
149
|
-
await testdriver.type("This is a test note added by TestDriver automation.");
|
|
150
|
-
|
|
151
|
-
// Regenerate note - click make note more concise
|
|
152
|
-
console.log("Looking for note regeneration option...");
|
|
153
|
-
try {
|
|
154
|
-
const makeNoteConcise = await testdriver.find("Make note more concise button or option");
|
|
155
|
-
await makeNoteConcise.click();
|
|
156
|
-
console.log("Clicked make note more concise");
|
|
157
|
-
|
|
158
|
-
// Wait for note to regenerate
|
|
159
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
160
|
-
|
|
161
|
-
// Verify note regeneration completed
|
|
162
|
-
const noteRegenerated = await testdriver.assert("note has been regenerated or updated");
|
|
163
|
-
expect(noteRegenerated).toBeTruthy();
|
|
164
|
-
} catch {
|
|
165
|
-
console.log("Could not find or click make note more concise option");
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Look for kebab menu on the right to access patient profile
|
|
169
|
-
console.log("Looking for kebab menu on the right...");
|
|
170
|
-
|
|
171
|
-
// Try to find the menu - it might be a three-dot menu or settings icon on the right side
|
|
172
|
-
const kebabMenu = await testdriver.find("three dots menu or kebab menu on the right side of the page");
|
|
173
|
-
await kebabMenu.click();
|
|
174
|
-
|
|
175
|
-
// Wait for menu to open
|
|
176
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
177
|
-
|
|
178
|
-
// Look for patient profile option
|
|
179
|
-
const patientProfile = await testdriver.find("Patient Profile or Edit Profile option in menu");
|
|
180
|
-
await patientProfile.click();
|
|
181
|
-
|
|
182
|
-
// Wait for patient profile form to load
|
|
183
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
184
|
-
|
|
185
|
-
// Verify patient profile form is displayed
|
|
186
|
-
const profileForm = await testdriver.assert("patient profile form or edit patient page is visible");
|
|
187
|
-
expect(profileForm).toBeTruthy();
|
|
188
|
-
|
|
189
|
-
// ========================================================================
|
|
190
|
-
// CHECKPOINT 5: Patient Profile Opened
|
|
191
|
-
// If test fails after this point, comment out all code above this checkpoint
|
|
192
|
-
// ========================================================================
|
|
193
|
-
|
|
194
|
-
// Fill out patient details
|
|
195
|
-
console.log("Filling out patient details...");
|
|
196
|
-
try {
|
|
197
|
-
// Look for phone number field as an example
|
|
198
|
-
const phoneField = await testdriver.find("phone number field or mobile number input");
|
|
199
|
-
await phoneField.click();
|
|
200
|
-
await testdriver.type("555-0123");
|
|
201
|
-
console.log("Filled phone number");
|
|
202
|
-
|
|
203
|
-
// Look for email field
|
|
204
|
-
try {
|
|
205
|
-
const emailFieldProfile = await testdriver.find("email address field in the patient profile");
|
|
206
|
-
await emailFieldProfile.click();
|
|
207
|
-
await testdriver.type("patient@example.com");
|
|
208
|
-
console.log("Filled email address");
|
|
209
|
-
} catch {
|
|
210
|
-
console.log("Email field not found");
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Look for and click the save button
|
|
214
|
-
const saveButton = await testdriver.find("Save button or Submit button");
|
|
215
|
-
await saveButton.click();
|
|
216
|
-
console.log("Clicked save button");
|
|
217
|
-
|
|
218
|
-
// Wait for save to complete
|
|
219
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
220
|
-
|
|
221
|
-
// Verify save was successful
|
|
222
|
-
const saveSuccess = await testdriver.assert("changes were saved successfully or save confirmation appears");
|
|
223
|
-
expect(saveSuccess).toBeTruthy();
|
|
224
|
-
} catch (error) {
|
|
225
|
-
console.log("Could not complete patient profile form:", error.message);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Take final screenshot
|
|
229
|
-
const finalScreenshot = await testdriver.screenshot();
|
|
230
|
-
expect(finalScreenshot).toBeDefined();
|
|
231
|
-
|
|
232
|
-
console.log("✅ Test completed successfully! Remember to uncomment all checkpoints for final validation.");
|
|
233
|
-
});
|
|
234
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Type Checking Demo
|
|
5
|
-
*
|
|
6
|
-
* This file demonstrates the strict type checking and autocomplete features
|
|
7
|
-
* of the TestDriver SDK. Open this file in VS Code and notice:
|
|
8
|
-
*
|
|
9
|
-
* 1. Method autocomplete when you type `client.`
|
|
10
|
-
* 2. Parameter autocomplete for enum values like action, direction, method
|
|
11
|
-
* 3. Inline documentation showing parameter types and descriptions
|
|
12
|
-
* 4. Type warnings if you use invalid values
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const TestDriver = require("../../sdk.js");
|
|
16
|
-
|
|
17
|
-
async function typeCheckingDemo() {
|
|
18
|
-
const client = new TestDriver(process.env.TD_API_KEY);
|
|
19
|
-
|
|
20
|
-
await client.auth();
|
|
21
|
-
await client.connect();
|
|
22
|
-
|
|
23
|
-
// Try typing these and see the autocomplete:
|
|
24
|
-
|
|
25
|
-
// 1. Action parameter - should autocomplete: 'click', 'right-click', 'double-click', 'hover', 'drag-start', 'drag-end'
|
|
26
|
-
await client.hoverText("Submit", null, "click");
|
|
27
|
-
|
|
28
|
-
// 2. Scroll direction - should autocomplete: 'up', 'down', 'left', 'right'
|
|
29
|
-
await client.scroll("asdf", 300);
|
|
30
|
-
|
|
31
|
-
// 3. Text match method - should autocomplete: 'ai', 'turbo'
|
|
32
|
-
await client.waitForText("Welcome", 5000, "turbo");
|
|
33
|
-
|
|
34
|
-
// 4. Keyboard keys - should autocomplete all valid keys
|
|
35
|
-
await client.pressKeys(["enter", "tab", "escape"]);
|
|
36
|
-
|
|
37
|
-
// 5. Exec language - should autocomplete: 'js', 'pwsh'
|
|
38
|
-
await client.exec("js", 'console.log("Hello")', 5000);
|
|
39
|
-
|
|
40
|
-
// 6. Scroll method - should autocomplete: 'keyboard', 'mouse'
|
|
41
|
-
await client.scrollUntilText("Contact", "down", 10000);
|
|
42
|
-
|
|
43
|
-
await client.disconnect();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Uncomment to run:
|
|
47
|
-
// typeCheckingDemo().catch(console.error);
|
|
48
|
-
|
|
49
|
-
module.exports = typeCheckingDemo;
|