testdriverai 7.0.0 → 7.1.1
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/README.md +126 -0
- package/agent/index.js +7 -9
- package/agent/interface.js +13 -2
- package/agent/lib/commands.js +795 -136
- package/agent/lib/redraw.js +124 -39
- package/agent/lib/sandbox.js +40 -3
- package/agent/lib/sdk.js +21 -0
- package/agent/lib/valid-version.js +2 -2
- package/debugger/index.html +1 -1
- package/docs/docs.json +86 -71
- package/docs/guide/best-practices-polling.mdx +154 -0
- 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/_drafts/best-practices.mdx +486 -0
- package/docs/v7/_drafts/caching-ai.mdx +215 -0
- package/docs/v7/_drafts/caching-selectors.mdx +400 -0
- package/docs/v7/_drafts/caching.mdx +366 -0
- package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
- package/docs/v7/_drafts/core.mdx +459 -0
- package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
- package/docs/v7/_drafts/debugging.mdx +349 -0
- package/docs/v7/_drafts/error-handling.mdx +501 -0
- package/docs/v7/_drafts/faq.mdx +393 -0
- package/docs/v7/_drafts/hooks.mdx +360 -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/performance.mdx +517 -0
- package/docs/v7/_drafts/presets.mdx +210 -0
- package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
- package/docs/v7/_drafts/provision.mdx +266 -0
- package/docs/{QUICK_START_TEST_RECORDING.md → v7/_drafts/quick-start-test-recording.mdx} +3 -3
- package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
- package/docs/v7/{guides → _drafts}/self-hosting.mdx +1 -1
- package/docs/v7/_drafts/troubleshooting.mdx +526 -0
- package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
- package/docs/v7/_drafts/vitest.mdx +535 -0
- package/docs/v7/api/{ai.mdx → act.mdx} +24 -24
- package/docs/v7/api/client.mdx +1 -1
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/elements.mdx +143 -41
- package/docs/v7/api/find.mdx +258 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/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 +380 -0
- 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 +320 -141
- 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/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/playwright.mdx +3 -3
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +303 -0
- package/docs/v7/presets/electron.mdx +453 -0
- package/docs/v7/presets/vscode.mdx +417 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/examples/run-tests-with-recording.sh +2 -2
- package/interfaces/cli/commands/init.js +358 -0
- package/interfaces/vitest-plugin.mjs +393 -103
- package/lib/core/Dashcam.js +506 -0
- package/lib/core/index.d.ts +150 -0
- package/lib/core/index.js +12 -0
- package/lib/presets/index.mjs +331 -0
- package/lib/vitest/hooks.d.ts +119 -0
- package/lib/vitest/hooks.mjs +316 -0
- package/lib/vitest/setup.mjs +44 -0
- package/package.json +13 -3
- package/sdk.d.ts +350 -44
- package/sdk.js +818 -105
- package/{self-hosted.yml → setup/aws/self-hosted.yml} +1 -1
- package/test/manual/test-console-logs.test.mjs +42 -0
- package/test/manual/test-init.sh +54 -0
- package/test/manual/test-provision-auth.mjs +22 -0
- package/test/testdriver/assert.test.mjs +41 -0
- package/test/testdriver/auto-cache-key-demo.test.mjs +56 -0
- package/test/testdriver/chrome-extension.test.mjs +89 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/drag-and-drop.test.mjs +7 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/element-not-found.test.mjs +6 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-js.test.mjs +6 -18
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-output.test.mjs +9 -21
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-pwsh.test.mjs +14 -26
- package/{testdriver/acceptance-sdk → test/testdriver}/focus-window.test.mjs +8 -20
- package/{testdriver/acceptance-sdk → test/testdriver}/formatted-logging.test.mjs +5 -20
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-image.test.mjs +10 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text-with-description.test.mjs +7 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text.test.mjs +5 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/match-image.test.mjs +7 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/press-keys.test.mjs +5 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/prompt.test.mjs +7 -19
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-keyboard.test.mjs +6 -20
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-image.test.mjs +6 -18
- package/test/testdriver/scroll-until-text.test.mjs +28 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll.test.mjs +12 -21
- package/test/testdriver/setup/lifecycleHelpers.mjs +262 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/setup/testHelpers.mjs +25 -20
- package/test/testdriver/type.test.mjs +45 -0
- package/vitest.config.mjs +11 -56
- 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/mcp.json +0 -9
- package/.vscode/settings.json +0 -14
- package/CODEOWNERS +0 -3
- package/MIGRATION.md +0 -389
- package/SDK_README.md +0 -1122
- 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/debug-screenshot-1763401388589.png +0 -0
- package/mcp-server/AI_GUIDELINES.md +0 -57
- package/scripts/view-test-results.mjs +0 -96
- 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/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 -44
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +0 -42
- package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
- package/testdriver/acceptance-sdk/type-checking-demo.js +0 -49
- package/testdriver/acceptance-sdk/type.test.mjs +0 -84
- 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/{CONTRIBUTING.md → docs/v7/_drafts/contributing.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/migration.mdx +0 -0
- /package/{PLUGIN_MIGRATION.md → docs/v7/_drafts/plugin-migration.mdx} +0 -0
- /package/{PROMPT_CACHE.md → docs/v7/_drafts/prompt-cache.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/{SDK_LOGGING.md → docs/v7/_drafts/sdk-logging.mdx} +0 -0
- /package/{SDK_MIGRATION.md → docs/v7/_drafts/sdk-migration.mdx} +0 -0
- /package/docs/{TEST_RECORDING.md → v7/_drafts/test-recording.mdx} +0 -0
- /package/docs/v7/{README.md → overview/readme.mdx} +0 -0
- /package/{debug-locate-response.js → test/manual/debug-locate-response.js} +0 -0
- /package/{test-find-api.js → test/manual/test-find-api.js} +0 -0
- /package/{test-prompt-cache.js → test/manual/test-prompt-cache.js} +0 -0
- /package/{test-sandbox-render.js → test/manual/test-sandbox-render.js} +0 -0
- /package/{test-sdk-methods.js → test/manual/test-sdk-methods.js} +0 -0
- /package/{test-sdk-refactor.js → test/manual/test-sdk-refactor.js} +0 -0
- /package/{test-stack-trace.mjs → test/manual/test-stack-trace.mjs} +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}/setup/globalTeardown.mjs +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/setup/vitestSetup.mjs +0 -0
|
@@ -3,29 +3,15 @@
|
|
|
3
3
|
* Converted from: testdriver/acceptance/hover-text.yaml
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
8
|
|
|
13
9
|
describe("Hover Text Test", () => {
|
|
14
|
-
|
|
10
|
+
it("should click Sign In and verify error message", async (context) => {
|
|
11
|
+
const testdriver = TestDriver(context, { headless: true, newSandbox: true, cacheKey: 'hover-text-test' });
|
|
12
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
13
|
|
|
16
|
-
beforeEach(async (context) => {
|
|
17
|
-
testdriver = createTestClient({ task: context.task });
|
|
18
|
-
|
|
19
|
-
await setupTest(testdriver);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(async (context) => {
|
|
23
|
-
await teardownTest(testdriver, { task: context.task });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should click Sign In and verify error message", async () => {
|
|
27
14
|
// Click on Sign In button using new find() API
|
|
28
|
-
await testdriver.focusApplication("Google Chrome");
|
|
29
15
|
|
|
30
16
|
const signInButton = await testdriver.find(
|
|
31
17
|
"Sign In, black button below the password field",
|
|
@@ -5,32 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
import path, { dirname } from "path";
|
|
7
7
|
import { fileURLToPath } from "url";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
performLogin,
|
|
12
|
-
setupTest,
|
|
13
|
-
teardownTest,
|
|
14
|
-
} from "./setup/testHelpers.mjs";
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
10
|
+
import { performLogin } from "./setup/testHelpers.mjs";
|
|
15
11
|
|
|
16
12
|
// Get the directory of the current module
|
|
17
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
14
|
const __dirname = dirname(__filename);
|
|
19
15
|
|
|
20
16
|
describe("Match Image Test", () => {
|
|
21
|
-
|
|
17
|
+
it("should match shopping cart image and verify empty cart", async (context) => {
|
|
18
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
19
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
testdriver = createTestClient({ task: context.task });
|
|
25
|
-
|
|
26
|
-
await setupTest(testdriver);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
afterEach(async (context) => {
|
|
30
|
-
await teardownTest(testdriver, { task: context.task });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should match shopping cart image and verify empty cart", async () => {
|
|
21
|
+
//
|
|
34
22
|
// Perform login first
|
|
35
23
|
await performLogin(testdriver);
|
|
36
24
|
|
|
@@ -3,28 +3,14 @@
|
|
|
3
3
|
* Converted from: testdriver/acceptance/press-keys.yaml
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
8
|
|
|
13
9
|
describe("Press Keys Test", () => {
|
|
14
|
-
|
|
10
|
+
it("should create tabs and navigate using keyboard shortcuts", async (context) => {
|
|
11
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
13
|
|
|
16
|
-
beforeEach(async (context) => {
|
|
17
|
-
testdriver = createTestClient({ task: context.task });
|
|
18
|
-
|
|
19
|
-
await setupTest(testdriver);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(async (context) => {
|
|
23
|
-
await teardownTest(testdriver, { task: context.task });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should create tabs and navigate using keyboard shortcuts", async () => {
|
|
27
|
-
await testdriver.focusApplication("Google Chrome");
|
|
28
14
|
const signInButton = await testdriver.find(
|
|
29
15
|
"Sign In, black button below the password field",
|
|
30
16
|
);
|
|
@@ -3,27 +3,15 @@
|
|
|
3
3
|
* Converted from: testdriver/acceptance/prompt.yaml
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
8
|
|
|
13
9
|
describe.skip("Prompt Test", () => {
|
|
14
|
-
|
|
10
|
+
it("should execute AI-driven prompts", async (context) => {
|
|
11
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
testdriver = createTestClient({ task: context.task });
|
|
18
|
-
|
|
19
|
-
await setupTest(testdriver);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(async (context) => {
|
|
23
|
-
await teardownTest(testdriver, { task: context.task });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should execute AI-driven prompts", async () => {
|
|
14
|
+
//
|
|
27
15
|
// Note: The SDK doesn't have a direct equivalent to YAML prompts without commands.
|
|
28
16
|
// This would typically be handled by the AI agent interpreting natural language.
|
|
29
17
|
// For SDK usage, you need to use explicit commands.
|
|
@@ -37,7 +25,7 @@ describe.skip("Prompt Test", () => {
|
|
|
37
25
|
// This test is skipped as it requires explicit SDK implementation
|
|
38
26
|
// You would need to implement these as explicit SDK calls
|
|
39
27
|
|
|
40
|
-
await testdriver.
|
|
28
|
+
await testdriver.act("log in");
|
|
41
29
|
|
|
42
30
|
const result = await testdriver.assert("the testdriver sandbox is visible");
|
|
43
31
|
expect(result).toBeTruthy();
|
|
@@ -3,29 +3,15 @@
|
|
|
3
3
|
* Converted from: testdriver/acceptance/scroll-keyboard.yaml
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
8
|
|
|
13
9
|
describe("Scroll Keyboard Test", () => {
|
|
14
|
-
|
|
10
|
+
it("should navigate to webhamster.com and scroll with keyboard", async (context) => {
|
|
11
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
testdriver = createTestClient({
|
|
18
|
-
task: context.task,
|
|
19
|
-
redrawThreshold: 0.5, // Higher threshold for scroll test
|
|
20
|
-
});
|
|
21
|
-
await setupTest(testdriver);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
afterEach(async (context) => {
|
|
25
|
-
await teardownTest(testdriver, { task: context.task });
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("should navigate to webhamster.com and scroll with keyboard", async () => {
|
|
14
|
+
//
|
|
29
15
|
// Navigate to https://www.webhamster.com/
|
|
30
16
|
await testdriver.focusApplication("Google Chrome");
|
|
31
17
|
const urlBar = await testdriver.find(
|
|
@@ -3,27 +3,15 @@
|
|
|
3
3
|
* Converted from: testdriver/acceptance/scroll-until-image.yaml
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
8
|
|
|
13
9
|
describe("Scroll Until Image Test", () => {
|
|
14
|
-
|
|
10
|
+
it("should scroll until brown colored house image appears", async (context) => {
|
|
11
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
12
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
testdriver = createTestClient({ task: context.task });
|
|
18
|
-
|
|
19
|
-
await setupTest(testdriver);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(async (context) => {
|
|
23
|
-
await teardownTest(testdriver, { task: context.task });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should scroll until brown colored house image appears", async () => {
|
|
14
|
+
//
|
|
27
15
|
// Navigate to Wikipedia page
|
|
28
16
|
await testdriver.pressKeys(["ctrl", "l"]);
|
|
29
17
|
await testdriver.type("https://en.wikipedia.org/wiki/Leonardo_da_Vinci");
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestDriver SDK - Scroll Until Text Test (Vitest)
|
|
3
|
+
* Converted from: testdriver/acceptance/scroll-until-text.yaml
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
8
|
+
import { performLogin } from "./setup/testHelpers.mjs";
|
|
9
|
+
|
|
10
|
+
describe("Scroll Until Text Test", () => {
|
|
11
|
+
it('should scroll until "testdriver socks" appears', async (context) => {
|
|
12
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
13
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
14
|
+
|
|
15
|
+
//
|
|
16
|
+
// Perform login first
|
|
17
|
+
await performLogin(testdriver);
|
|
18
|
+
|
|
19
|
+
// Scroll until text appears
|
|
20
|
+
await testdriver.focusApplication("Google Chrome");
|
|
21
|
+
await testdriver.scrollUntilText({ text: "testdriver socks", direction: "down" });
|
|
22
|
+
|
|
23
|
+
// Assert testdriver socks appears on screen
|
|
24
|
+
await testdriver.focusApplication("Google Chrome");
|
|
25
|
+
const result = await testdriver.assert("TestDriver Socks appears on screen");
|
|
26
|
+
expect(result).toBeTruthy();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TestDriver SDK - Scroll Test (Vitest)
|
|
3
3
|
* Converted from: testdriver/acceptance/scroll.yaml
|
|
4
|
+
*
|
|
5
|
+
* UPDATED: Now using chrome preset for automatic setup
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
createTestClient,
|
|
9
|
-
setupTest,
|
|
10
|
-
teardownTest,
|
|
11
|
-
} from "./setup/testHelpers.mjs";
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import { TestDriver } from "../../lib/vitest/hooks.mjs";
|
|
12
10
|
|
|
13
11
|
describe("Scroll Test", () => {
|
|
14
|
-
|
|
12
|
+
it("should navigate and scroll down the page", async (context) => {
|
|
13
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
14
|
+
await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// Give Chrome a moment to fully render the UI
|
|
17
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(async (context) => {
|
|
23
|
-
await teardownTest(testdriver, { task: context.task });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should navigate and scroll down the page", async () => {
|
|
27
|
-
// Navigate to webhamster.com
|
|
28
|
-
await testdriver.focusApplication("Google Chrome");
|
|
19
|
+
// Navigate to webhamster.com - just look for the domain, not the full path
|
|
29
20
|
const urlBar = await testdriver.find(
|
|
30
|
-
"testdriver-sandbox.vercel.app
|
|
21
|
+
"testdriver-sandbox.vercel.app, the URL in the address bar",
|
|
31
22
|
);
|
|
32
23
|
await urlBar.click();
|
|
33
24
|
await testdriver.pressKeys(["ctrl", "a"]);
|
|
@@ -44,7 +35,7 @@ describe("Scroll Test", () => {
|
|
|
44
35
|
await testdriver.scroll("down", 1000);
|
|
45
36
|
|
|
46
37
|
// Assert page is scrolled
|
|
47
|
-
const result = await testdriver.assert("the page is scrolled down");
|
|
38
|
+
const result = await testdriver.assert("the page is scrolled down, the hamster dance heading is not visible on the page");
|
|
48
39
|
expect(result).toBeTruthy();
|
|
49
40
|
});
|
|
50
41
|
});
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle Helpers
|
|
3
|
+
* Shared lifecycle hook functions (prerun, postrun)
|
|
4
|
+
*
|
|
5
|
+
* LEGACY: These helpers are thin wrappers around the new Dashcam class.
|
|
6
|
+
* For new code, prefer using the Dashcam class directly:
|
|
7
|
+
*
|
|
8
|
+
* import { Dashcam } from 'testdriverai/core';
|
|
9
|
+
* const dashcam = new Dashcam(client);
|
|
10
|
+
* await dashcam.auth();
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import Dashcam from '../../../lib/core/Dashcam.js';
|
|
14
|
+
|
|
15
|
+
// Module-level cache to maintain Dashcam instance state across helper calls
|
|
16
|
+
const dashcamInstances = new WeakMap();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get or create Dashcam instance for a client
|
|
20
|
+
* @private
|
|
21
|
+
* @param {TestDriver} client
|
|
22
|
+
* @param {object} options
|
|
23
|
+
* @returns {Dashcam}
|
|
24
|
+
*/
|
|
25
|
+
function getDashcam(client, options = {}) {
|
|
26
|
+
if (!dashcamInstances.has(client)) {
|
|
27
|
+
dashcamInstances.set(client, new Dashcam(client, options));
|
|
28
|
+
}
|
|
29
|
+
return dashcamInstances.get(client);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Authenticate dashcam with API key
|
|
34
|
+
* @deprecated Use `new Dashcam(client)` and `dashcam.auth()` instead
|
|
35
|
+
* @param {TestDriver} client - TestDriver client
|
|
36
|
+
* @param {string} apiKey - Dashcam API key (default: 4e93d8bf-3886-4d26-a144-116c4063522d)
|
|
37
|
+
*/
|
|
38
|
+
export async function authDashcam(
|
|
39
|
+
client,
|
|
40
|
+
apiKey = "4e93d8bf-3886-4d26-a144-116c4063522d",
|
|
41
|
+
) {
|
|
42
|
+
const dashcam = getDashcam(client, { apiKey });
|
|
43
|
+
await dashcam.auth();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Add log file tracking to dashcam
|
|
48
|
+
* @deprecated Use `new Dashcam(client)` and `dashcam.addFileLog()` instead
|
|
49
|
+
* @param {TestDriver} client - TestDriver client
|
|
50
|
+
* @param {string} logName - Name for the log in dashcam (default: "TestDriver Log")
|
|
51
|
+
*/
|
|
52
|
+
export async function addDashcamLog(client, logName = "TestDriver Log") {
|
|
53
|
+
const dashcam = getDashcam(client);
|
|
54
|
+
const logPath = client.os === "windows"
|
|
55
|
+
? "C:\\Users\\testdriver\\Documents\\testdriver.log"
|
|
56
|
+
: "/tmp/testdriver.log";
|
|
57
|
+
|
|
58
|
+
// Create log file first
|
|
59
|
+
if (client.os === "windows") {
|
|
60
|
+
await client.exec("pwsh", `New-Item -ItemType File -Path "${logPath}" -Force`, 10000, true);
|
|
61
|
+
} else {
|
|
62
|
+
await client.exec("sh", `touch ${logPath}`, 10000, true);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await dashcam.addFileLog(logPath, logName);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Start dashcam recording
|
|
70
|
+
* @deprecated Use `new Dashcam(client)` and `dashcam.start()` instead
|
|
71
|
+
* @param {TestDriver} client - TestDriver client
|
|
72
|
+
*/
|
|
73
|
+
export async function startDashcam(client) {
|
|
74
|
+
const dashcam = getDashcam(client);
|
|
75
|
+
await dashcam.start();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Stop dashcam recording and retrieve URL
|
|
80
|
+
* @deprecated Use `new Dashcam(client)` and `dashcam.stop()` instead
|
|
81
|
+
* @param {TestDriver} client - TestDriver client
|
|
82
|
+
* @returns {Promise<string|null>} Dashcam URL if available
|
|
83
|
+
*/
|
|
84
|
+
export async function stopDashcam(client) {
|
|
85
|
+
console.log("🎬 Stopping dashcam and retrieving URL...");
|
|
86
|
+
const dashcam = getDashcam(client);
|
|
87
|
+
const url = await dashcam.stop();
|
|
88
|
+
|
|
89
|
+
if (url) {
|
|
90
|
+
console.log("✅ Found dashcam URL:", url);
|
|
91
|
+
console.log("🎥 Dashcam URL:", url);
|
|
92
|
+
} else {
|
|
93
|
+
console.warn("⚠️ No replay URL found in dashcam output");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return url;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Launch Chrome browser with guest mode
|
|
101
|
+
* @param {TestDriver} client - TestDriver client
|
|
102
|
+
* @param {string} url - URL to open (default: https://testdriver-sandbox.vercel.app/)
|
|
103
|
+
*/
|
|
104
|
+
export async function launchChrome(
|
|
105
|
+
client,
|
|
106
|
+
url = "http://testdriver-sandbox.vercel.app/",
|
|
107
|
+
) {
|
|
108
|
+
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
109
|
+
|
|
110
|
+
if (client.os === "windows") {
|
|
111
|
+
await client.exec(
|
|
112
|
+
"pwsh",
|
|
113
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--guest", "${url}"`,
|
|
114
|
+
30000,
|
|
115
|
+
);
|
|
116
|
+
} else {
|
|
117
|
+
await client.exec(
|
|
118
|
+
shell,
|
|
119
|
+
`google-chrome --start-maximized --disable-fre --no-default-browser-check --no-first-run --guest "${url}" >/dev/null 2>&1 &`,
|
|
120
|
+
30000,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Launch Chrome for Testing browser with guest mode
|
|
127
|
+
* @param {TestDriver} client - TestDriver client
|
|
128
|
+
* @param {string} url - URL to open (default: https://testdriver-sandbox.vercel.app/)
|
|
129
|
+
*/
|
|
130
|
+
export async function launchChromeForTesting(
|
|
131
|
+
client,
|
|
132
|
+
url = "http://testdriver-sandbox.vercel.app/",
|
|
133
|
+
) {
|
|
134
|
+
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
135
|
+
|
|
136
|
+
if (client.os === "windows") {
|
|
137
|
+
// Windows Chrome for Testing path would need to be determined
|
|
138
|
+
// For now, fallback to regular Chrome on Windows
|
|
139
|
+
await client.exec(
|
|
140
|
+
"pwsh",
|
|
141
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--guest", "${url}"`,
|
|
142
|
+
30000,
|
|
143
|
+
);
|
|
144
|
+
} else {
|
|
145
|
+
await client.exec(
|
|
146
|
+
shell,
|
|
147
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --guest "${url}" >/dev/null 2>&1 &`,
|
|
148
|
+
30000,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Launch Chrome for Testing with a Chrome extension loaded
|
|
155
|
+
* @param {TestDriver} client - TestDriver client
|
|
156
|
+
* @param {string} extensionId - Chrome Web Store extension ID (e.g., "cjpalhdlnbpafiamejdnhcphjbkeiagm" for uBlock Origin)
|
|
157
|
+
* @param {string} url - URL to open (default: https://testdriver-sandbox.vercel.app/)
|
|
158
|
+
* @example
|
|
159
|
+
* // Launch with uBlock Origin extension
|
|
160
|
+
* await launchChromeExtension(client, "cjpalhdlnbpafiamejdnhcphjbkeiagm");
|
|
161
|
+
*
|
|
162
|
+
* // Launch with multiple extensions (comma-separated)
|
|
163
|
+
* await launchChromeExtension(client, "cjpalhdlnbpafiamejdnhcphjbkeiagm,nngceckbapebfimnlniiiahkandclblb");
|
|
164
|
+
*/
|
|
165
|
+
export async function launchChromeExtension(
|
|
166
|
+
client,
|
|
167
|
+
extensionId,
|
|
168
|
+
url = "http://testdriver-sandbox.vercel.app/",
|
|
169
|
+
) {
|
|
170
|
+
const shell = client.os === "windows" ? "pwsh" : "sh";
|
|
171
|
+
|
|
172
|
+
if (client.os === "windows") {
|
|
173
|
+
// Windows Chrome for Testing path would need to be determined
|
|
174
|
+
// For now, fallback to regular Chrome on Windows
|
|
175
|
+
await client.exec(
|
|
176
|
+
"pwsh",
|
|
177
|
+
`Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "--load-extension=${extensionId}", "${url}"`,
|
|
178
|
+
30000,
|
|
179
|
+
);
|
|
180
|
+
} else {
|
|
181
|
+
await client.exec(
|
|
182
|
+
shell,
|
|
183
|
+
`chrome-for-testing --start-maximized --disable-fre --no-default-browser-check --no-first-run --load-extension=${extensionId} "${url}" >/dev/null 2>&1 &`,
|
|
184
|
+
30000,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Wait for page to load by polling for text
|
|
191
|
+
* @param {TestDriver} client - TestDriver client
|
|
192
|
+
* @param {string} text - Text to wait for
|
|
193
|
+
* @param {number} maxAttempts - Maximum number of attempts (default: 60)
|
|
194
|
+
* @param {number} pollInterval - Interval between polls in ms (default: 5000)
|
|
195
|
+
*/
|
|
196
|
+
export async function waitForPage(
|
|
197
|
+
client,
|
|
198
|
+
text,
|
|
199
|
+
maxAttempts = 60,
|
|
200
|
+
pollInterval = 5000,
|
|
201
|
+
) {
|
|
202
|
+
console.log("Waiting for page to load, looking for text:", text);
|
|
203
|
+
let element;
|
|
204
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
205
|
+
element = await client.find(text);
|
|
206
|
+
if (element.found()) break;
|
|
207
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Run prerun lifecycle hooks
|
|
213
|
+
* Implements lifecycle/prerun.yaml functionality
|
|
214
|
+
* @param {TestDriver} client - TestDriver client
|
|
215
|
+
*/
|
|
216
|
+
export async function runPrerun(client) {
|
|
217
|
+
await authDashcam(client);
|
|
218
|
+
await addDashcamLog(client);
|
|
219
|
+
await startDashcam(client);
|
|
220
|
+
await launchChrome(client);
|
|
221
|
+
await waitForPage(client, "TestDriver.ai Sandbox");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Run prerun lifecycle hooks with Chrome for Testing
|
|
226
|
+
* Implements lifecycle/prerun.yaml functionality using Chrome for Testing
|
|
227
|
+
* @param {TestDriver} client - TestDriver client
|
|
228
|
+
*/
|
|
229
|
+
export async function runPrerunChromeForTesting(client) {
|
|
230
|
+
await authDashcam(client);
|
|
231
|
+
await addDashcamLog(client);
|
|
232
|
+
await startDashcam(client);
|
|
233
|
+
await launchChromeForTesting(client);
|
|
234
|
+
await waitForPage(client, "TestDriver.ai Sandbox");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Run prerun lifecycle hooks with Chrome extension loaded
|
|
239
|
+
* Implements lifecycle/prerun.yaml functionality with a Chrome extension
|
|
240
|
+
* @param {TestDriver} client - TestDriver client
|
|
241
|
+
* @param {string} extensionId - Chrome Web Store extension ID to load
|
|
242
|
+
* @example
|
|
243
|
+
* // Launch with uBlock Origin extension
|
|
244
|
+
* await runPrerunChromeExtension(client, "cjpalhdlnbpafiamejdnhcphjbkeiagm");
|
|
245
|
+
*/
|
|
246
|
+
export async function runPrerunChromeExtension(client, extensionId) {
|
|
247
|
+
await authDashcam(client);
|
|
248
|
+
await addDashcamLog(client);
|
|
249
|
+
await startDashcam(client);
|
|
250
|
+
await launchChromeExtension(client, extensionId);
|
|
251
|
+
await waitForPage(client, "TestDriver.ai Sandbox");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Run postrun lifecycle hooks
|
|
256
|
+
* Implements lifecycle/postrun.yaml functionality
|
|
257
|
+
* @param {TestDriver} client - TestDriver client
|
|
258
|
+
* @returns {Promise<string|null>} Dashcam URL if available
|
|
259
|
+
*/
|
|
260
|
+
export async function runPostrun(client) {
|
|
261
|
+
return await stopDashcam(client);
|
|
262
|
+
}
|
|
@@ -11,26 +11,26 @@ import path, { dirname } from "path";
|
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
12
|
import TestDriver from "../../../sdk.js";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
addDashcamLog,
|
|
15
|
+
authDashcam,
|
|
16
|
+
launchChrome,
|
|
17
|
+
runPostrun,
|
|
18
|
+
runPrerun,
|
|
19
|
+
startDashcam,
|
|
20
|
+
stopDashcam,
|
|
21
|
+
waitForPage,
|
|
22
22
|
} from "./lifecycleHelpers.mjs";
|
|
23
23
|
|
|
24
24
|
// Re-export lifecycle helpers for backward compatibility
|
|
25
25
|
export {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
addDashcamLog,
|
|
27
|
+
authDashcam,
|
|
28
|
+
launchChrome,
|
|
29
|
+
runPostrun,
|
|
30
|
+
runPrerun,
|
|
31
|
+
startDashcam,
|
|
32
|
+
stopDashcam,
|
|
33
|
+
waitForPage
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
// Get the directory of the current module
|
|
@@ -264,7 +264,7 @@ export function createTestClient(options = {}) {
|
|
|
264
264
|
apiKey: process.env.TD_API_KEY,
|
|
265
265
|
apiRoot: process.env.TD_API_ROOT || "https://testdriver-api.onrender.com",
|
|
266
266
|
// headless: false,
|
|
267
|
-
|
|
267
|
+
newSandbox: true,
|
|
268
268
|
// ip: '18.217.194.23'
|
|
269
269
|
// ...clientOptions,
|
|
270
270
|
// cache: false,
|
|
@@ -522,7 +522,11 @@ export async function teardownTest(client, options = {}) {
|
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
// Note: Duration is calculated by Vitest and passed via result.duration
|
|
525
|
-
// We
|
|
525
|
+
// We include it in the test result file so the reporter can use it
|
|
526
|
+
|
|
527
|
+
// Get duration from Vitest result
|
|
528
|
+
const result = options.task.result?.();
|
|
529
|
+
const duration = result?.duration || 0;
|
|
526
530
|
|
|
527
531
|
// Write test result with dashcam URL, platform, and metadata
|
|
528
532
|
const testResult = {
|
|
@@ -536,6 +540,7 @@ export async function teardownTest(client, options = {}) {
|
|
|
536
540
|
: null,
|
|
537
541
|
platform: client.os, // Include platform from SDK client (source of truth)
|
|
538
542
|
timestamp: Date.now(),
|
|
543
|
+
duration: duration, // Include duration from Vitest
|
|
539
544
|
};
|
|
540
545
|
|
|
541
546
|
fs.writeFileSync(testResultFile, JSON.stringify(testResult, null, 2));
|
|
@@ -614,9 +619,9 @@ export async function performLogin(
|
|
|
614
619
|
await usernameField.click();
|
|
615
620
|
await client.type(username);
|
|
616
621
|
|
|
617
|
-
// Enter password
|
|
622
|
+
// Enter password (marked as secret so it's not logged or stored)
|
|
618
623
|
await client.pressKeys(["tab"]);
|
|
619
|
-
await client.type(password);
|
|
624
|
+
await client.type(password, { secret: true });
|
|
620
625
|
|
|
621
626
|
// Submit form
|
|
622
627
|
await client.pressKeys(["tab"]);
|