continuum-test.orangesync.tech · Agent: agent-test.orangesync.techfeat/ansible-one-click-deploy · Date: 2026-07-07
| File | Tests | Scope |
|---|---|---|
comprehensive.spec.ts | 53 | Boot/routing, landing, projects CRUD, project home, marketplace, routstr, dashboard, chat dock, auth/session, persistence, theme, agent API |
coverage-gaps.spec.ts | 69 / 2 | Sidebar detail, landing detail, modal validation, project home detail, marketplace detail, routstr detail, dashboard detail, chat detail, auth edge cases, persistence detail |
auth-flow.spec.ts | 19 | Token injection → logged-in UI, NIP-07 login flow, post-login agent API, sign-out & edge cases |
| Total | 141 / 2 | Every view, component, and authentication path |
| Step | How Tested | Result |
|---|---|---|
| Token format | a.EPOCH_SECONDS.b.c (4 dot-parts, 2nd = expiry) | Valid |
| Token injection → logged-in UI | Inject a.9999999999.b.c via localStorage | W01-W04 |
| NIP-07 signer mock | page.addInitScript → window.nostr.signEvent | X02 |
| Auth verify interception | page.route → return fake token | X02 |
| 401 auto-clear | Fake token hits real /api/wallet/balance | Z02 |
| Invalid token rejection | Wrong format (not 4 parts) | Z03 |
| Expired token rejection | a.1.b.c (epoch = 1, 1970) | Z04 |
| Sign out | Click "Sign out", check localStorage cleared | Z01 |
| Challenge endpoint | POST /api/auth/challenge | X03 |
| Protected API endpoints | 401 without valid token | Y03-Y06 |
✓ A01: SPA loads and renders content ✓ A02: Landing route hides sidebar ✓ A03: Non-landing routes show sidebar ✓ A04: Sidebar has 6 nav items ✓ A05: Brand button navigates to landing ✓ A06: Unknown hash redirects to landing ✓ A07: Each nav item navigates to its route ✓ A08: Active nav item gets highlighted ✓ B01: Landing shows hero with torii gate SVG ✓ B02: Landing has "Open the demo" button ✓ B03: Landing shows status pill ✓ B04: Landing has promises/pillars section ✓ C01: Projects page shows seeded projects ✓ C02: Project cards are clickable ✓ C03: New Project button opens modal ✓ C04: Modal has tabs (blank/github/ngit) ✓ C05: Create blank project ✓ C06: Cancel new project closes modal ✓ D01: Project home shows project name ✓ D02: Project home shows milestones ✓ D03: Project home shows todos ✓ D04: Add a todo item ✓ D05: Toggle a todo checkbox ✓ D06: Breadcrumb navigates back ✓ D07: Unknown project shows empty state ✓ E01: Marketplace shows task listings ✓ E02: Marketplace has diverse listings ✓ E03: "Our tasks" filter exists ✓ F01: Routstr page renders ✓ F02: Routstr shows model info ✓ F03: Routstr shows usage/balance ✓ G01: Dashboard renders with content ✓ G02: Dashboard shows project summary ✓ H01: Chat dock visible on non-landing ✓ H02: Chat dock can be expanded ✓ H03: Chat greeting present ✓ H04: Send a mock chat message ✓ I01: Session button present ✓ I02: Session button shows label ✓ I03: Login without NIP-07 shows modal ✓ J01: Data persists across reloads ✓ J02: Projects persist after navigation ✓ K01: Theme toggle button exists ✓ K02: Theme toggle switches theme ✓ K03: Theme persists in localStorage ✓ L01: Health endpoint responds ✓ L02: Challenge endpoint issues challenge ✓ L03: Verify without event fails 400 ✓ L04: Admin routes reject without token ✓ L05: Chat endpoint rejects without auth ✓ L06: Memory endpoints require auth ✓ L07: Pending path validation ✓ L08: Health includes memory_unlocked
✓ M01: Keyboard Enter on nav-item navigates to its route ✓ M02: Keyboard Space on nav-item navigates to its route ✓ M03: "Our tasks" nav item strips query and lands on marketplace ✓ M04: Sidebar nav-badge shows project count (≥2) ✓ M05: Brand has correct aria-label and navigates to landing ✓ M06: Theme toggle button has data-theme-toggle attribute ✓ M07: Session button shows "Demo mode" text ✓ N01: Landing hero renders exact title "The Gateway Project." and eyebrow ✓ N02: Landing lede paragraph is present ✓ N03: Torii gate SVG has correct aria-label and viewBox 220 260 ✓ N04: Status microcopy pill shows demo-mode or agent-reachable ✓ N05: Promises section has 4 cards (Local-first, Nostr-native, Pay-per-request, Human-in-the-loop) ✓ N06: Pillars section renders 4 items with k/v/note ✓ N07: Status list renders ok/next/later items ✓ N08: Footer has external links to GitHub and Torii Quest ✓ N09: Secondary CTA reflects logged-out state (shows Login text) ✓ O01: Project progress bar shows sane width percentage ✓ O02: Add card "+" opens the modal ✓ O03: Empty project name shows inline error "Give the project a name." ✓ O04: GitHub tab reveals repo URL row with github.com placeholder ✓ O05: GitHub tab rejects non-github.com URL ✓ O06: ngit tab validates ngit:// prefix ✓ O07: Duplicate slug is rejected with error (name "Continuum" collides) ✓ O08: Backdrop click closes the modal ✓ O09: Tab switching shows correct active class (blank→github→ngit) ✓ P01: "Open source ↗" button opens a popup window to GitHub ✓ P02: Delete button is hidden for continuum project ✓ P03: Delete button is hidden for torii-quest project ✓ P04: Milestone rows render with correct pill classes (.done→.ok, .active→.hot) ✓ P05: Overview strip renders 3 stat cards (Progress, Open todos, Sessions) ✓ P06: Crumbs renders "Projects" link that navigates back to /projects ✓ P07: Todo section has add-input with correct placeholder "+ add a todo…" ✓ P08: Files section renders with .kind/.mono/.size for seeded files ✓ Q01: "Ours" rows carry the .ours class and show "ours" pill ✓ Q02: Search input filters rows to matching names (e.g. "strfry") ✓ Q03: Empty filter search shows ∅ empty state with "No tasks match" ✓ Q04: "Show ours only" toggle restricts to .ours rows, button text flips ✓ Q05: Header pill counts total (N total) and ours (N ours) ✓ Q06: Task rows are keyboard-focusable (role="button" tabindex="0") ✓ Q07: Complexity select filters by size, resets correctly ✓ R01: Not-connected state shows "not connected" pill and Cashu balance ✓ R02: Model picker lists 8+ seeded models with DeepSeek Chat default ✓ R03: Clicking a non-selected model selects it and re-renders ✓ R04: Endpoint input displays default value https://api.routstr.com ✓ R05: Monthly budget input displays default value 25000 ✓ R06: Usage stats section renders 4 metrics (Requests, Sats, Tokens in/out) ✓ R07: Demo mode Connect bumps balance to [12000,20000] range ✓ R08: Connect → Disconnect → pill shows "not connected", balance resets ✓ S01: Dashboard renders 3 aggregate stat cards ✓ S02: "By project" section lists seeded projects (≥2) ✓ S03: Project row click (Torii Quest) navigates to /projects/torii-quest ✓ S04: Oversight link to torii-quest.pplx.app present with target="_blank" ✓ S05: Overall progress shows a percentage ✓ T01: Chat dock starts collapsed with .collapsed class, toggle shows ▲ ✓ T02: Toggle expands (▼) and collapses (▲) the dock ✓ T03: Chat context shows "context · Projects" on projects page ✓ T04: Chat context shows "Marketplace" on marketplace page ✓ T05: Chat context shows "Continuum" on project home page ✓ T06: Chat greeting message (AI) present when dock is collapsed ✓ T07: Shift+Enter inserts newline instead of sending ✓ T08: Send button is present with text "Send" ✓ T09: Chat dock is hidden on landing page ✓ U01: Session button click shows login modal or demo mode info - U02: Skipped (environment-dependent: Demo mode check requires no agent) - U03: Skipped (environment-dependent: Sign-out check) ✓ V01: Seed data is populated on first boot (3 cards = 2 seeded + 1 add) ✓ V02: Created project survives page reload ✓ V03: Added todo survives page reload ✓ V04: Routstr model selection survives reload ✓ V05: Marketplace sort preference does NOT persist (view-local state) ✓ V06: Theme persists in localStorage across reloads
✓ W01: Session button shows "Sign out" when logged in ✓ W02: Landing CTA shows "Go to your dashboard" when logged in ✓ W03: Chat dock greeting differs when logged in (mentions "Signed in") ✓ W04: Logged-in state survives page reload ✓ X01: Login button with no NIP-07 shows "signer not found" modal ✓ X02: Login with NIP-07 stub completes full flow (window.nostr + page.route) ✓ X03: Challenge endpoint returns valid challenge (≥32 hex chars, expires_in=300, kind=22242) ✓ Y01: Chat sends POST to agent when logged in (intercepted via page.route) ✓ Y02: Wallet balance endpoint called when logged in on Routstr ✓ Y03: Protected agent endpoints return 401 without valid token ✓ Y04: Health endpoint returns full metadata (ok, service, version, time, memory_unlocked) ✓ Y05: Chat endpoint rejects invalid body shapes ✓ Y06: Reflect endpoint rejects without auth (401) ✓ Z01: Sign out from sidebar clears token and changes UI button text ✓ Z02: 401 from agent API auto-clears the session token ✓ Z03: Invalid token format (not 4 parts) does NOT set logged-in state ✓ Z04: Expired token does NOT set logged-in state ✓ Z05: Landing CTA navigates to dashboard when logged in ✓ Z06: Verify endpoint rejects empty body (400)
Format: a.EPOCH_SECONDS.xxx.xxx (4 dot-separated parts) Example: a.9999999999.b.c Storage: localStorage key 'continuum.session.v1' Validation: isLoggedIn() checks parts.length === 4, parseInt(parts[1]) * 1000 > Date.now() Auto-clear: 401 from any agent endpoint → clearStoredToken()
1. page.addInitScript(() => { window.nostr = { signEvent: async (ev) => ({ ...ev, id:'00...', pubkey:'00...', sig:'00...' }) }; })
2. page.route('/api/auth/verify', async (route) => { route.fulfill({ status:200, body: JSON.stringify({ token: FAKE_TOKEN, expires_at: FUTURE_EXP }) }); });
3. Click "Login" → NIP-07 signs challenge → POST /api/auth/verify → token stored → UI switches to logged-in
page.route('/api/chat', async (route) => {
chatRequested = true;
route.fulfill({ status:200, body: JSON.stringify({ reply: 'Mock reply.' }) });
});
page.route('/api/wallet/balance', async (route) => {
walletCalled = true;
route.fulfill({ status:200, body: JSON.stringify({ balance_sats: 42000 }) });
});
Target: continuum-test.orangesync.tech (VPS2, Caddy + static SPA)
Agent: agent-test.orangesync.tech (Fastify, version 0.2.5-alpha, memory_unlocked: false)
Generated 2026-07-07 · Continuum E2E Test Suite · TEST_EVIDENCE.md