Audit of the full E2E suite (43 specs) surfaced four issues that were
hiding behind 'all 96/96 web unit tests pass' but actually meant the
browser-level coverage was broken end-to-end. All four are fixed and
the suite now passes 43/43.
1. Port conflict silently testing wrong app. playwright.config.ts hard-
coded baseURL=http://localhost:3000 with reuseExistingServer:true on
non-CI hosts. When the dev host had ANY service on :3000 (Grafana,
chronomind, etc), Playwright happily ran the entire E2E suite
against the wrong app and reported the unrelated failures as
'real'. Now honors NOTELETT_WEB_PORT env (default 3000) so a
contributor can opt into any free port and Playwright drives both
baseURL and the dev-server PORT consistently.
2. Missing test dependency. web/e2e/accessibility.spec.ts imports
@axe-core/playwright but web/package.json never declared it.
The accessibility coverage was DOA — every CI run that included
this spec would module-not-found-error before a single check ran.
Added @axe-core/playwright to devDependencies.
3. Mock that never fires. smart-actions.spec.ts 'history API mock
returns items' used page.route() to mock /api/note-prompts/history
then bypassed the mock entirely with page.request.get() (which uses
Playwright's separate request context, not the browser context that
page.route intercepts). The request went to the dev server and got
404. Replaced with page.goto + page.evaluate(fetch(...)) so the
browser-side fetch hits the page.route mock as intended.
4. Missing visual-regression baselines. visual-regression.spec.ts had
no committed baseline screenshots for dashboard / workspaces /
search. First run on a clean host always reported 'snapshot doesn't
exist, writing actual'. Generated and committed darwin baselines.
Verified end-to-end (NOTELETT_WEB_PORT=3050 against this host's free
port):
43 passed (34.8s)
Total test-tier counts on main now:
backend unit + integration (memory) 380/380
backend cosmos emulator (live) 4/4
web vitest 96/96
mobile vitest 97/97
web playwright e2e 43/43
---
TOTAL 620/620
Web:
- New lib/billing-client.ts: factory wrapper using shared getAccessToken.
- Add @bytelyst/billing-client to web deps.
Mobile:
- New lib/billing-client.ts: factory wrapper using MMKV token storage.
- New lib/platform-api.ts: typed platform-client wrapper for settings,
sessions, and profile management.
- Add @bytelyst/billing-client and @bytelyst/platform-client to deps.
All @bytelyst/* packages are internal to the ByteLyst ecosystem and
published to the private Gitea registry. Using "*" eliminates version
bump noise — always resolves to latest available.
Phase 3 (Web UX Polish) of the execution roadmap:
- Add reusable Pagination component for list views
- Fix getNoteDetail to avoid fetching all notes when workspaceId is unknown
- Add file upload button to ArtifactPanel using uploadArtifact() from blob-client
- Remove unused zustand and zod from web dependencies
- SSR safety already addressed via existing lazy-init patterns
Made-with: Cursor
Phase 0.5 of the execution roadmap:
- Remove phantom @bytelyst/ui dep, add sonner for toast notifications
- Replace custom error.tsx, not-found.tsx, loading.tsx with @bytelyst/dashboard-components
- Replace raw extraction-client.ts with @bytelyst/extraction createExtractionClient()
- Add @bytelyst/dashboard-components and @bytelyst/extraction to transpilePackages
Made-with: Cursor
Phase 1 — Platform SDK integration:
- Mobile: added @bytelyst/telemetry-client, feature-flag-client, kill-switch-client, blob-client deps
- Mobile: created src/lib/platform.ts — centralized platform init (telemetry, flags, kill-switch, blob)
- Mobile: wired initPlatform() into root layout startup
- Web: refactored blob-client.ts to use shared @bytelyst/blob-client (eliminates hand-rolled SAS fetch code)
- Web: added @bytelyst/blob-client dep
DRY: Both web and mobile now use the same @bytelyst/blob-client package for blob operations.
Verification: web typecheck + mobile typecheck pass.