| Layer | Framework | Files | Scope |
|---|---|---|---|
| E2E (Puppeteer) | Mocha + Chai + Mochawesome | 14 suites | Full user journeys in headless Chrome |
| Support Content | Vitest + happy-dom | 18 files (6 per locale) | Article structure, i18n parity |
| Component Unit | Vitest + @vue/test-utils | 0 files | Not started |
| Store Unit | Vitest | 0 files | Not started |
| API Service Unit | Vitest | 0 files | Not started |
Vitest, @vue/test-utils, and happy-dom are already installed and configured in src/vue/app/vitest.config.ts. The test directory is src/vue/app/tests/.
| Suite | File | What It Covers |
|---|---|---|
| test-101 | test-101.landing-page.spec.js |
Page load, header, hero, brand selector, step indicator |
| test-102 | test-102.payment-step.spec.js |
Plan cards, prices, payment methods, terms checkbox |
| test-103 | test-103.language-switcher.spec.js |
i18n switching, localStorage persistence |
| test-104 | test-104.i18n-completeness.spec.js |
Translation keys present across all locales |
| test-105 | test-105.user-journey.spec.js |
Full flow: brand > connect > plan > pay, state persistence |
| test-106 | test-106.back-navigation.spec.js |
Back button, step indicator clicks, round-trip navigation |
| test-107 | test-107.support-page.spec.js |
Search, topic/article navigation, breadcrumbs |
| test-108 | test-108.service-agreement.spec.js |
Modal open/close, content per locale (en/fi/sv) |
| test-109 | test-109.error-states.spec.js |
Network failures, API errors, graceful degradation |
| test-110 | test-110.session-persistence.spec.js |
Session state persistence across page reloads |
| test-201 | test-201.payment-wizard.spec.js |
Stripe checkout: plan > card details > payment > return |
| test-202 | test-202.payment-paypal.spec.js |
PayPal selection, switching, E2E |
| test-301 | test-301.tesla-oauth-login.spec.js |
Tesla OAuth: login, MFA/TOTP, consent, callback, session |
| test-302 | test-302.report-dashboard.spec.js |
Multi-vehicle tabs, report sections, PDF download |
All E2E tests live in src/nodejs/the-bot/test/.
Located in src/vue/app/tests/support/{en,fi,sv}/:
| Test | What It Validates |
|---|---|
| 001.article-count | Expected number of articles per topic |
| 002.frontmatter-integrity | YAML frontmatter structure (title, slug, order) |
| 003.slug-consistency | Unique slugs, no duplicates |
| 004.i18n-keys | Translation keys used in articles exist in locale files |
| 005.cross-locale-parity | Same articles exist in all 3 locales |
| 006.content-body | Uniqueness (en) or language detection (fi, sv) |
Impact: HIGH — 16 components, zero unit coverage. All testing relies on E2E only.
| Component | Lines | Complexity | E2E Coverage |
|---|---|---|---|
PaymentStep.vue |
282 | High (plans, vouchers, quotes, methods, terms) | Partial (Stripe only) |
ReportDashboard.vue |
315 | High (multi-vehicle tabs, PDF, charts) | None |
App.vue |
~200 | High (OAuth/payment callbacks, step routing) | Partial |
OAuthStep.vue |
~80 | Medium (Tesla redirect, error states) | Yes (test-301) |
GeneratingStep.vue |
~60 | Medium (async report generation, error fallback) | None |
PaymentGateway.vue |
~80 | Medium (payment confirmation, auto-advance) | None |
StepIndicator.vue |
~60 | Medium (active/completed/clickable states) | Yes (test-106) |
BrandSelector.vue |
~100 | Medium (infinite scroll, selection, connect) | Yes (test-101) |
Header.vue |
~80 | Low-Medium (nav, language, mobile menu) | Partial |
Hero.vue |
~60 | Low (CTA, scroll interaction) | Yes (test-101) |
SupportPage.vue |
~120 | Medium (search, breadcrumbs, 3 views) | None |
ServiceAgreement.vue |
~50 | Low (modal, markdown render) | None |
BrandCarousel.vue |
~40 | Low (infinite loop animation) | None |
SupportedBrands.vue |
~40 | Low (grid, badges) | None |
FeeRow.vue |
~20 | Low (label + currency format) | None |
Footer.vue |
~20 | Low (copyright, agreement link) | Partial |
Impact: HIGH — stores/app.ts manages all application state. Zero unit tests.
Areas to test:
- State initialization — default values, localStorage hydration on mount
- Actions — setStep(), setSelectedBrandId(), setSessionId(), setSelectedPlan(), setPaymentMethod(), setCatalog(), setCurrentQuote(), setVehicleReports(), setActiveReportVin()
- Navigation — navigateToSupport() saves previous step, returnFromSupport() restores it
- Reset — reset() clears all state and localStorage keys
- Persistence — watchers sync state to localStorage with cpt-* prefixed keys
- Edge cases — corrupted localStorage values, missing keys, concurrent updates
Impact: HIGH — services/api.ts contains 10+ functions calling the backend. Zero unit tests.
Areas to test (mock fetch):
- Tesla OAuth — initiateTeslaOAuth(brand) returns authUrl
- Session — getSessionVehicles(id), selectVehiclesAndPackage(id, vins, pkg)
- Payment — createPaymentIntent(id, method), verifyPayment(paymentId)
- Pricing/CPQ — fetchCatalog(), fetchQuote(id, voucher?), validateVoucher(code)
- Reports — generateReports(id), getSessionReports(id), generatePdfReport(report)
- Auth header — Bearer token injected from localStorage when present
- Error handling — HTTP errors, network failures, malformed JSON responses
| Scenario | Current Status |
|---|---|
| PayPal payment flow | Covered (test-202) |
| Google Pay / Apple Pay | Not tested (placeholder providers) |
| Report download / PDF generation | Covered (test-302) |
| GeneratingStep loading + completion | Not tested |
| PaymentGateway confirmation screen | Not tested |
| SupportPage search + navigation | Covered (test-107) |
| ServiceAgreement modal | Covered (test-108) |
| Error states (network failure, API errors) | Covered (test-109) |
| Session persistence | Covered (test-110) |
| Mobile viewport / responsiveness | Not tested (desktop only) |
| Accessibility (keyboard nav, ARIA) | Not tested |
| Deep-link / direct URL navigation | Not tested |
| Multi-vehicle selection and tabbed reports | Covered (test-302) |
These are pure logic — no DOM, fast execution, catch regressions early.
Target directory: src/vue/app/tests/unit/
tests/
├── support/ # (existing) content validation
└── unit/
├── stores/
│ └── app.test.ts
└── services/
└── api.test.ts
Store tests (app.test.ts):
- Test each action mutates state correctly
- Test localStorage read on init, write on change
- Test reset() clears everything
- Test navigateToSupport() / returnFromSupport() round-trip
- Test corrupted localStorage graceful handling
API service tests (api.test.ts):
- Mock globalThis.fetch or use vi.fn()
- Test each endpoint function sends correct method, URL, headers, body
- Test Bearer token included when localStorage has access_token
- Test error response handling (4xx, 5xx, network error)
Target directory: src/vue/app/tests/components/
tests/
├── support/
├── unit/
└── components/
├── PaymentStep.test.ts
├── ReportDashboard.test.ts
├── StepIndicator.test.ts
├── GeneratingStep.test.ts
├── PaymentGateway.test.ts
├── OAuthStep.test.ts
├── BrandSelector.test.ts
├── Header.test.ts
├── SupportPage.test.ts
└── ...
Priority order:
1. PaymentStep — plan selection, voucher input, quote display, method toggle, terms gate
2. ReportDashboard — multi-vehicle tabs, report sections, PDF trigger
3. StepIndicator — active/completed/clickable state rendering
4. GeneratingStep — loading state, API call, error fallback
5. PaymentGateway — confirmation display, auto-advance timer
6. OAuthStep — connect button, redirect trigger, error display
7. Header — language switch, mobile menu toggle, support nav
8. BrandSelector — brand items render, selection, connect prompt
9. SupportPage — search, topic/article navigation, breadcrumbs
10. Remaining: ServiceAgreement, Hero, FeeRow, Footer, BrandCarousel, SupportedBrands
Target directory: src/nodejs/the-bot/test/
Already implemented: test-107 (support-page), test-108 (service-agreement), test-109 (error-states), test-110 (session-persistence), test-202 (payment-paypal), test-302 (report-dashboard).
Suggested additional suites:
- test-111.mobile-viewport — Mobile viewport / responsive layout testing
- test-112.accessibility — Keyboard navigation, ARIA attributes
- test-203.payment-googlepay — Google Pay flow (when provider is implemented)
- test-204.payment-applepay — Apple Pay flow (when provider is implemented)
vitest run --coveragevitest.config.ts:
typescript
test: {
coverage: {
provider: 'v8',
include: ['src/components/**', 'src/stores/**', 'src/services/**'],
thresholds: {
statements: 60,
branches: 50,
functions: 60,
lines: 60,
}
}
}ci.yaml) — fail build on threshold violation# From bnc-cpt-wui/src/vue/app/
npm test # All vitest tests
npm run test:watch # Watch mode
npm run test:support # Support content tests only
# Specific test file
npx vitest run tests/unit/stores/app.test.ts
# Via shell actions (from bnc-cpt-utl/)
./run -a do_run_wui_tests # Headless in Docker
PUPPETEER_HEADLESS=false ./run -a do_run_wui_tests_local # Headed locally
# Via Make (from bnc-cpt-utl/)
make test-wui # Headless in Docker
make test-wui-headed # Headed on host
# Tesla OAuth tests
ENV=dev ./run -a do_run_tesla_login_test
TESLA_SESSION_ID=xxx ENV=dev ./run -a do_run_tesla_login_test
dat/test-report/report.html (Mochawesome HTML)dat/test-report/screenshots/