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
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Observable & Debuggable"
|
|
3
|
+
description: "Complete visibility into test execution with replays, logs, and analytics"
|
|
4
|
+
icon: "microscope"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Debugging test failures is effortless with TestDriver's comprehensive observability features - video replays, detailed logs, network monitoring, and performance metrics.
|
|
8
|
+
|
|
9
|
+
## Video Replays with Dashcam
|
|
10
|
+
|
|
11
|
+
Every test automatically records a video replay for easy debugging:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { test } from 'vitest';
|
|
15
|
+
import { chrome } from 'testdriverai/presets';
|
|
16
|
+
|
|
17
|
+
test('with automatic replay', async (context) => {
|
|
18
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
19
|
+
url: 'https://example.com'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await testdriver.find('button').click();
|
|
23
|
+
await testdriver.find('input').type('test data');
|
|
24
|
+
await testdriver.find('submit').click();
|
|
25
|
+
|
|
26
|
+
// After test completes, view replay
|
|
27
|
+
console.log('Watch replay:', dashcam.url);
|
|
28
|
+
// Output: https://console.testdriver.ai/dashcam/abc123def456
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
<Card title="Dashcam Features" icon="video">
|
|
33
|
+
**Every replay includes:**
|
|
34
|
+
|
|
35
|
+
- Full video recording of test execution
|
|
36
|
+
- Timeline with all actions marked
|
|
37
|
+
- Screenshots at key moments
|
|
38
|
+
- Console logs synchronized with video
|
|
39
|
+
- Network requests with timing
|
|
40
|
+
- Element highlights on interactions
|
|
41
|
+
- Slow-motion playback
|
|
42
|
+
- Frame-by-frame stepping
|
|
43
|
+
</Card>
|
|
44
|
+
|
|
45
|
+
[View all replays at app.testdriver.ai](https://app.testdriver.ai)
|
|
46
|
+
|
|
47
|
+
## Replay Features
|
|
48
|
+
|
|
49
|
+
<Tabs>
|
|
50
|
+
<Tab title="Video Playback">
|
|
51
|
+
- **Full resolution** - Recorded at native screen resolution
|
|
52
|
+
- **Variable speed** - Play at 0.25x to 2x speed
|
|
53
|
+
- **Frame-by-frame** - Step through individual frames
|
|
54
|
+
- **Jump to action** - Click timeline to jump to any action
|
|
55
|
+
- **Download** - Save replay as MP4
|
|
56
|
+
</Tab>
|
|
57
|
+
|
|
58
|
+
<Tab title="Action Timeline">
|
|
59
|
+
```
|
|
60
|
+
00:00.000 Test started
|
|
61
|
+
00:01.234 find('submit button')
|
|
62
|
+
00:02.567 click()
|
|
63
|
+
00:03.890 find('email input')
|
|
64
|
+
00:04.123 type('user@example.com')
|
|
65
|
+
00:05.456 find('password input')
|
|
66
|
+
00:06.789 type('***') [secret]
|
|
67
|
+
00:07.012 find('Login button')
|
|
68
|
+
00:07.345 click()
|
|
69
|
+
00:09.678 assert('Dashboard is visible')
|
|
70
|
+
00:10.901 Test passed ✓
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Click any action to jump to that moment in the replay.
|
|
74
|
+
</Tab>
|
|
75
|
+
|
|
76
|
+
<Tab title="Element Highlights">
|
|
77
|
+
All interactions show visual highlights:
|
|
78
|
+
|
|
79
|
+
- **Green outline** - Element being located
|
|
80
|
+
- **Blue flash** - Click action
|
|
81
|
+
- **Yellow highlight** - Hover action
|
|
82
|
+
- **Red outline** - Failed assertion
|
|
83
|
+
- **Purple marker** - Type action
|
|
84
|
+
</Tab>
|
|
85
|
+
|
|
86
|
+
<Tab title="Sharing">
|
|
87
|
+
Share replays with your team:
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
// Public link (anyone with link can view)
|
|
91
|
+
console.log('Public replay:', dashcam.url);
|
|
92
|
+
|
|
93
|
+
// Team-only link (requires login)
|
|
94
|
+
console.log('Team replay:', dashcam.privateUrl);
|
|
95
|
+
|
|
96
|
+
// Embed in CI/CD
|
|
97
|
+
console.log('Embed:', dashcam.embedUrl);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Replays can be:
|
|
101
|
+
- Shared via link
|
|
102
|
+
- Embedded in CI reports
|
|
103
|
+
- Downloaded as video
|
|
104
|
+
- Exported with logs
|
|
105
|
+
</Tab>
|
|
106
|
+
</Tabs>
|
|
107
|
+
|
|
108
|
+
## Application Logs
|
|
109
|
+
|
|
110
|
+
Access all console output from your application:
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
test('with console logging', async (context) => {
|
|
114
|
+
const { testdriver } = await chrome(context, {
|
|
115
|
+
url: 'https://example.com',
|
|
116
|
+
captureConsole: true // Enable console capture
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Your test code
|
|
120
|
+
await testdriver.find('button').click();
|
|
121
|
+
|
|
122
|
+
// Application console logs are captured automatically
|
|
123
|
+
// View them in Dashcam replay
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
<Accordion title="Captured Log Types">
|
|
128
|
+
**Browser Console:**
|
|
129
|
+
- `console.log()` - Debug messages
|
|
130
|
+
- `console.warn()` - Warnings
|
|
131
|
+
- `console.error()` - Errors
|
|
132
|
+
- `console.info()` - Info messages
|
|
133
|
+
- `console.debug()` - Debug messages
|
|
134
|
+
|
|
135
|
+
**Application Logs:**
|
|
136
|
+
- JavaScript errors and exceptions
|
|
137
|
+
- Unhandled promise rejections
|
|
138
|
+
- Network errors (404, 500, etc.)
|
|
139
|
+
- Security errors (CORS, CSP)
|
|
140
|
+
- React/Vue warnings
|
|
141
|
+
</Accordion>
|
|
142
|
+
|
|
143
|
+
## Network Monitoring
|
|
144
|
+
|
|
145
|
+
Complete visibility into all network activity:
|
|
146
|
+
|
|
147
|
+
<Card title="Network Request Details" icon="network-wired">
|
|
148
|
+
**For every request, view:**
|
|
149
|
+
|
|
150
|
+
- URL and method (GET, POST, etc.)
|
|
151
|
+
- Request headers
|
|
152
|
+
- Request payload/body
|
|
153
|
+
- Response status code
|
|
154
|
+
- Response headers
|
|
155
|
+
- Response body
|
|
156
|
+
- Timing breakdown (DNS, Connect, TLS, Wait, Download)
|
|
157
|
+
- Size (request and response)
|
|
158
|
+
- Initiated by (script/user action)
|
|
159
|
+
</Card>
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
test('network monitoring', async (context) => {
|
|
163
|
+
const { testdriver } = await chrome(context, {
|
|
164
|
+
url: 'https://api.example.com',
|
|
165
|
+
captureNetwork: true
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await testdriver.find('Load data button').click();
|
|
169
|
+
|
|
170
|
+
// Network requests are captured and shown in Dashcam
|
|
171
|
+
// Filter by:
|
|
172
|
+
// - XHR/Fetch
|
|
173
|
+
// - Images
|
|
174
|
+
// - Scripts
|
|
175
|
+
// - Stylesheets
|
|
176
|
+
// - Failed requests
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Network Waterfall
|
|
181
|
+
|
|
182
|
+
View request timing in a waterfall chart:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
GET /api/users ████████░░░░░░░░ 245ms
|
|
186
|
+
GET /api/posts ░░░░████████████ 412ms
|
|
187
|
+
GET /avatar.jpg ░░░░░░░░░░██░░░░ 87ms
|
|
188
|
+
POST /api/comment ░░░░░░░░░░░░████ 156ms
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Failed Requests
|
|
192
|
+
|
|
193
|
+
Easily identify failed network requests:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
❌ GET /api/data 404 Not Found (234ms)
|
|
197
|
+
❌ POST /api/submit 500 Internal Error (891ms)
|
|
198
|
+
❌ GET /image.jpg Failed to fetch (timeout)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Performance Metrics
|
|
202
|
+
|
|
203
|
+
Track application performance over time:
|
|
204
|
+
|
|
205
|
+
<Tabs>
|
|
206
|
+
<Tab title="Page Load Metrics">
|
|
207
|
+
```javascript
|
|
208
|
+
test('measure performance', async (context) => {
|
|
209
|
+
const { testdriver } = await chrome(context, {
|
|
210
|
+
url: 'https://example.com',
|
|
211
|
+
capturePerformance: true
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Metrics automatically captured:
|
|
215
|
+
// - First Contentful Paint (FCP)
|
|
216
|
+
// - Largest Contentful Paint (LCP)
|
|
217
|
+
// - Time to Interactive (TTI)
|
|
218
|
+
// - Total Blocking Time (TBT)
|
|
219
|
+
// - Cumulative Layout Shift (CLS)
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
View Core Web Vitals in Dashcam replay.
|
|
224
|
+
</Tab>
|
|
225
|
+
|
|
226
|
+
<Tab title="Resource Timing">
|
|
227
|
+
```
|
|
228
|
+
Resource Performance:
|
|
229
|
+
- HTML: 234ms
|
|
230
|
+
- CSS: 456ms (3 files)
|
|
231
|
+
- JavaScript: 892ms (12 files)
|
|
232
|
+
- Images: 1.2s (45 files)
|
|
233
|
+
- Fonts: 234ms (2 files)
|
|
234
|
+
Total: 3.0s
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Identify slow resources in your application.
|
|
238
|
+
</Tab>
|
|
239
|
+
|
|
240
|
+
<Tab title="CPU Usage">
|
|
241
|
+
```
|
|
242
|
+
CPU Usage During Test:
|
|
243
|
+
Average: 34%
|
|
244
|
+
Peak: 67% (at 00:05.234)
|
|
245
|
+
Idle: 15%
|
|
246
|
+
|
|
247
|
+
High CPU events:
|
|
248
|
+
- 00:05.234: JavaScript parsing (67%)
|
|
249
|
+
- 00:08.901: Animation rendering (54%)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Available in enterprise plans.
|
|
253
|
+
</Tab>
|
|
254
|
+
|
|
255
|
+
<Tab title="Memory Usage">
|
|
256
|
+
```
|
|
257
|
+
Memory Usage:
|
|
258
|
+
Start: 45MB
|
|
259
|
+
Peak: 187MB (at 00:12.456)
|
|
260
|
+
End: 92MB
|
|
261
|
+
|
|
262
|
+
Potential leaks:
|
|
263
|
+
- 00:15.000: +45MB (no corresponding release)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Detect memory leaks in your application.
|
|
267
|
+
Available in enterprise plans.
|
|
268
|
+
</Tab>
|
|
269
|
+
</Tabs>
|
|
270
|
+
|
|
271
|
+
## Debug Screenshots
|
|
272
|
+
|
|
273
|
+
Automatic screenshots on failures:
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
try {
|
|
277
|
+
await testdriver.find('missing element');
|
|
278
|
+
} catch (error) {
|
|
279
|
+
// Automatic debug screenshot
|
|
280
|
+
console.log('Screenshot:', error.debugScreenshot); // Base64 image
|
|
281
|
+
console.log('Similarity:', error.similarity); // How close we got
|
|
282
|
+
console.log('Confidence:', error.confidence); // AI confidence
|
|
283
|
+
|
|
284
|
+
// Screenshot shows:
|
|
285
|
+
// - Full page at time of failure
|
|
286
|
+
// - Highlighted search area
|
|
287
|
+
// - Similar elements (if any)
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
<Card title="Debug Screenshot Features" icon="camera">
|
|
292
|
+
- Full page screenshot at failure point
|
|
293
|
+
- Annotated with attempted action
|
|
294
|
+
- Similar elements highlighted
|
|
295
|
+
- Bounding boxes for close matches
|
|
296
|
+
- Automatically attached to test report
|
|
297
|
+
</Card>
|
|
298
|
+
|
|
299
|
+
## Test Reports
|
|
300
|
+
|
|
301
|
+
Generate comprehensive test reports:
|
|
302
|
+
|
|
303
|
+
<Tabs>
|
|
304
|
+
<Tab title="HTML Report">
|
|
305
|
+
```bash
|
|
306
|
+
npx vitest run --reporter=html
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Generates interactive HTML report with:
|
|
310
|
+
- Pass/fail status for all tests
|
|
311
|
+
- Execution time per test
|
|
312
|
+
- Dashcam replay links
|
|
313
|
+
- Screenshots on failures
|
|
314
|
+
- Error messages and stack traces
|
|
315
|
+
</Tab>
|
|
316
|
+
|
|
317
|
+
<Tab title="JSON Report">
|
|
318
|
+
```bash
|
|
319
|
+
npx vitest run --reporter=json > report.json
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"testResults": [
|
|
325
|
+
{
|
|
326
|
+
"name": "user can login",
|
|
327
|
+
"status": "passed",
|
|
328
|
+
"duration": 12345,
|
|
329
|
+
"dashcamUrl": "https://console.testdriver.ai/dashcam/abc123",
|
|
330
|
+
"assertions": 3
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
</Tab>
|
|
336
|
+
|
|
337
|
+
<Tab title="JUnit XML">
|
|
338
|
+
```bash
|
|
339
|
+
npx vitest run --reporter=junit --outputFile=results.xml
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```xml
|
|
343
|
+
<testsuite name="login.test.js" tests="3" failures="0">
|
|
344
|
+
<testcase name="user can login" time="12.345">
|
|
345
|
+
<system-out>
|
|
346
|
+
Dashcam: https://console.testdriver.ai/dashcam/abc123
|
|
347
|
+
</system-out>
|
|
348
|
+
</testcase>
|
|
349
|
+
</testsuite>
|
|
350
|
+
```
|
|
351
|
+
</Tab>
|
|
352
|
+
|
|
353
|
+
<Tab title="Custom Report">
|
|
354
|
+
```javascript
|
|
355
|
+
import { BaseReporter } from 'vitest/reporters';
|
|
356
|
+
|
|
357
|
+
class CustomReporter extends BaseReporter {
|
|
358
|
+
onTestEnd(test) {
|
|
359
|
+
// Send to your analytics system
|
|
360
|
+
analytics.track('test_complete', {
|
|
361
|
+
name: test.name,
|
|
362
|
+
status: test.result.state,
|
|
363
|
+
duration: test.result.duration,
|
|
364
|
+
dashcamUrl: test.context.dashcam?.url
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export default {
|
|
370
|
+
test: {
|
|
371
|
+
reporters: [new CustomReporter()]
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
```
|
|
375
|
+
</Tab>
|
|
376
|
+
</Tabs>
|
|
377
|
+
|
|
378
|
+
## Analytics Dashboard
|
|
379
|
+
|
|
380
|
+
View test analytics at [console.testdriver.ai](https://console.testdriver.ai):
|
|
381
|
+
|
|
382
|
+
<CardGroup cols={2}>
|
|
383
|
+
<Card title="Test Trends" icon="chart-line">
|
|
384
|
+
- Pass/fail rate over time
|
|
385
|
+
- Average execution time
|
|
386
|
+
- Flaky test identification
|
|
387
|
+
- Most expensive tests
|
|
388
|
+
- Cache hit rates
|
|
389
|
+
</Card>
|
|
390
|
+
|
|
391
|
+
<Card title="Performance Trends" icon="gauge-high">
|
|
392
|
+
- Page load times
|
|
393
|
+
- Core Web Vitals
|
|
394
|
+
- Resource loading times
|
|
395
|
+
- API response times
|
|
396
|
+
- Performance regressions
|
|
397
|
+
</Card>
|
|
398
|
+
|
|
399
|
+
<Card title="Cost Analysis" icon="dollar-sign">
|
|
400
|
+
- Daily/weekly/monthly costs
|
|
401
|
+
- Cost per test
|
|
402
|
+
- Cost by team member
|
|
403
|
+
- Sandbox usage
|
|
404
|
+
- API call volume
|
|
405
|
+
</Card>
|
|
406
|
+
|
|
407
|
+
<Card title="Team Activity" icon="users">
|
|
408
|
+
- Tests run by user
|
|
409
|
+
- Most active tests
|
|
410
|
+
- Peak usage times
|
|
411
|
+
- Sandbox utilization
|
|
412
|
+
- Failed test hotspots
|
|
413
|
+
</Card>
|
|
414
|
+
</CardGroup>
|
|
415
|
+
|
|
416
|
+
## Failure Analysis
|
|
417
|
+
|
|
418
|
+
Quickly identify and diagnose test failures:
|
|
419
|
+
|
|
420
|
+
```javascript
|
|
421
|
+
// Failed test provides rich context
|
|
422
|
+
test('failing test', async (context) => {
|
|
423
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
424
|
+
url: 'https://example.com'
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
try {
|
|
428
|
+
await testdriver.find('missing button').click();
|
|
429
|
+
} catch (error) {
|
|
430
|
+
console.log('Failure details:', {
|
|
431
|
+
message: error.message,
|
|
432
|
+
dashcamUrl: dashcam.url,
|
|
433
|
+
screenshot: error.debugScreenshot,
|
|
434
|
+
similarity: error.similarity,
|
|
435
|
+
timestamp: error.timestamp,
|
|
436
|
+
sandboxId: context.sandboxId
|
|
437
|
+
});
|
|
438
|
+
throw error;
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Failure Report
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
❌ Test failed: user can login
|
|
447
|
+
|
|
448
|
+
Error: ElementNotFoundError: Could not find 'missing button'
|
|
449
|
+
at TestDriver.find (testdriver.js:123)
|
|
450
|
+
at login.test.js:15:24
|
|
451
|
+
|
|
452
|
+
Details:
|
|
453
|
+
- Similarity: 0.34 (no close match)
|
|
454
|
+
- Duration: 12.3s
|
|
455
|
+
- Dashcam: https://console.testdriver.ai/dashcam/abc123
|
|
456
|
+
- Screenshot: [attached]
|
|
457
|
+
- Sandbox: i-0abc123def456789
|
|
458
|
+
|
|
459
|
+
Recent actions:
|
|
460
|
+
1. navigate to https://example.com ✓
|
|
461
|
+
2. find('email input') ✓
|
|
462
|
+
3. type('user@example.com') ✓
|
|
463
|
+
4. find('missing button') ✗
|
|
464
|
+
|
|
465
|
+
Console errors:
|
|
466
|
+
- TypeError: Cannot read property 'x' of undefined (app.js:456)
|
|
467
|
+
- Warning: Missing key prop (React)
|
|
468
|
+
|
|
469
|
+
Network errors:
|
|
470
|
+
- 404: /api/user-settings (234ms)
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## CI/CD Integration
|
|
474
|
+
|
|
475
|
+
Integrate test results into your CI/CD pipeline:
|
|
476
|
+
|
|
477
|
+
<Tabs>
|
|
478
|
+
<Tab title="GitHub Actions">
|
|
479
|
+
```yaml
|
|
480
|
+
- name: Run tests
|
|
481
|
+
run: npx vitest run
|
|
482
|
+
env:
|
|
483
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
484
|
+
|
|
485
|
+
- name: Upload results
|
|
486
|
+
if: always()
|
|
487
|
+
uses: actions/upload-artifact@v3
|
|
488
|
+
with:
|
|
489
|
+
name: test-results
|
|
490
|
+
path: |
|
|
491
|
+
test-results.xml
|
|
492
|
+
.testdriver/dashcam-urls.txt
|
|
493
|
+
|
|
494
|
+
- name: Comment PR
|
|
495
|
+
if: failure()
|
|
496
|
+
uses: actions/github-script@v6
|
|
497
|
+
with:
|
|
498
|
+
script: |
|
|
499
|
+
const fs = require('fs');
|
|
500
|
+
const dashcamUrls = fs.readFileSync('.testdriver/dashcam-urls.txt', 'utf8');
|
|
501
|
+
github.rest.issues.createComment({
|
|
502
|
+
issue_number: context.issue.number,
|
|
503
|
+
body: `Tests failed. View replays:\n${dashcamUrls}`
|
|
504
|
+
});
|
|
505
|
+
```
|
|
506
|
+
</Tab>
|
|
507
|
+
|
|
508
|
+
<Tab title="Slack Notifications">
|
|
509
|
+
```javascript
|
|
510
|
+
// Post test results to Slack
|
|
511
|
+
import { WebClient } from '@slack/web-api';
|
|
512
|
+
|
|
513
|
+
test.afterEach(async (context) => {
|
|
514
|
+
if (context.task.result.state === 'fail') {
|
|
515
|
+
const slack = new WebClient(process.env.SLACK_TOKEN);
|
|
516
|
+
|
|
517
|
+
await slack.chat.postMessage({
|
|
518
|
+
channel: '#test-failures',
|
|
519
|
+
text: `Test failed: ${context.task.name}`,
|
|
520
|
+
attachments: [{
|
|
521
|
+
color: 'danger',
|
|
522
|
+
fields: [
|
|
523
|
+
{ title: 'Test', value: context.task.name },
|
|
524
|
+
{ title: 'Replay', value: context.dashcam.url },
|
|
525
|
+
{ title: 'Error', value: context.task.result.error.message }
|
|
526
|
+
]
|
|
527
|
+
}]
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
```
|
|
532
|
+
</Tab>
|
|
533
|
+
|
|
534
|
+
<Tab title="Jira Integration">
|
|
535
|
+
```javascript
|
|
536
|
+
// Automatically create Jira tickets for failures
|
|
537
|
+
import { JiraClient } from 'jira-client';
|
|
538
|
+
|
|
539
|
+
test.afterEach(async (context) => {
|
|
540
|
+
if (context.task.result.state === 'fail') {
|
|
541
|
+
const jira = new JiraClient({
|
|
542
|
+
host: 'company.atlassian.net',
|
|
543
|
+
apiVersion: '2'
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
await jira.addNewIssue({
|
|
547
|
+
fields: {
|
|
548
|
+
project: { key: 'TEST' },
|
|
549
|
+
summary: `Test failure: ${context.task.name}`,
|
|
550
|
+
description: `
|
|
551
|
+
Test failed: ${context.task.name}
|
|
552
|
+
|
|
553
|
+
Error: ${context.task.result.error.message}
|
|
554
|
+
|
|
555
|
+
Replay: ${context.dashcam.url}
|
|
556
|
+
|
|
557
|
+
Sandbox: ${context.sandboxId}
|
|
558
|
+
`,
|
|
559
|
+
issuetype: { name: 'Bug' }
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
```
|
|
565
|
+
</Tab>
|
|
566
|
+
</Tabs>
|
|
567
|
+
|
|
568
|
+
## Real-Time Monitoring
|
|
569
|
+
|
|
570
|
+
Monitor tests as they run:
|
|
571
|
+
|
|
572
|
+
```bash
|
|
573
|
+
# Watch test execution in real-time
|
|
574
|
+
npx vitest --reporter=verbose
|
|
575
|
+
|
|
576
|
+
# Output:
|
|
577
|
+
✓ login.test.js > user can login (12.3s)
|
|
578
|
+
→ find('email input') (1.2s)
|
|
579
|
+
→ type('user@example.com') (0.8s)
|
|
580
|
+
→ find('password input') (0.9s)
|
|
581
|
+
→ type('***') (0.7s) [secret]
|
|
582
|
+
→ find('Login button') (1.1s)
|
|
583
|
+
→ click() (0.4s)
|
|
584
|
+
→ assert('Dashboard is visible') (7.2s)
|
|
585
|
+
✓ Test passed
|
|
586
|
+
📹 Replay: https://console.testdriver.ai/dashcam/abc123
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
## Learn More
|
|
590
|
+
|
|
591
|
+
<CardGroup cols={2}>
|
|
592
|
+
<Card
|
|
593
|
+
title="Dashcam API"
|
|
594
|
+
icon="video"
|
|
595
|
+
href="/v7/api/dashcam"
|
|
596
|
+
>
|
|
597
|
+
Complete Dashcam documentation
|
|
598
|
+
</Card>
|
|
599
|
+
|
|
600
|
+
<Card
|
|
601
|
+
title="Debugging Guide"
|
|
602
|
+
icon="bug"
|
|
603
|
+
href="/v7/guides/debugging"
|
|
604
|
+
>
|
|
605
|
+
Debug failing tests effectively
|
|
606
|
+
</Card>
|
|
607
|
+
|
|
608
|
+
<Card
|
|
609
|
+
title="View Replays"
|
|
610
|
+
icon="play"
|
|
611
|
+
href="https://console.testdriver.ai"
|
|
612
|
+
>
|
|
613
|
+
Access your test replays
|
|
614
|
+
</Card>
|
|
615
|
+
|
|
616
|
+
<Card
|
|
617
|
+
title="Performance Guide"
|
|
618
|
+
icon="gauge-high"
|
|
619
|
+
href="/v7/guides/performance"
|
|
620
|
+
>
|
|
621
|
+
Optimize test performance
|
|
622
|
+
</Card>
|
|
623
|
+
</CardGroup>
|