End-to-End Test Flows
End-to-End Test Flows
Section titled “End-to-End Test Flows”Updated: 23/03/2026
Comprehensive test flows for Knowledge Hub pre-pilot quality gate. Each flow is a numbered sequence with preconditions, steps, expected outcomes, and pass/fail criteria.
Test environment: http://localhost:3000 with bun dev running. Auth:
All flows require authenticated session (admin role by default). Config:
playwright.config.ts — 2 browser projects (Desktop Chrome, Pixel 5 mobile).
Test data setup: Before running Flows 4-7, create test data using the E2E Test Data Setup Runbook. This covers bid creation, question insertion, response creation without AI, and cleanup procedures. Flows 6 (Export) and 7 (Template Completion) can be tested with zero AI API calls by inserting responses directly via SQL.
Automated E2E Spec Files
Section titled “Automated E2E Spec Files”15 spec files in e2e/tests/, each covering one or more manual flows.
Worker-scoped fixtures seed test data per worker to avoid cross-test
interference.
| # | Spec File | Manual Flow | Description |
|---|---|---|---|
| 1 | auth.spec.ts | Flow 0 | Authentication: unauthenticated redirect, login page elements, session persistence |
| 2 | browse-search.spec.ts | Flow 2 | Browse page: grid/list views, filters, sorting; Search page: semantic search, results |
| 3 | item-detail.spec.ts | Flow 3 | Item detail: page loading, metadata sidebar, content sections, breadcrumbs, mobile |
| 4 | qa-library.spec.ts | Flow 12 | Q&A Library: browsing, search, filtering, domain groups, virtualised list |
| 5 | coverage-page.spec.ts | Flow 13 | Coverage dashboard: summary cards, domain sections, gap identification |
| 6 | bid-pipeline.spec.ts | Flow 4 | Bid pipeline: bid list, bid detail, status filters, creation form, mobile |
| 7 | governance-review.spec.ts | Flow 8 | Review queue: loading, speed-review cards, verify/flag/skip, progress |
| 8 | settings.spec.ts | Flow 9 | Settings: sidebar navigation, section content, admin-only sections |
| 9 | role-gating.spec.ts | Flow 9 | Role-based gating: viewer/editor/admin nav items, settings visibility |
| 10 | layer-suggestion.spec.ts | — | Layer suggestion: banner on create page, layer filter, layer badges |
| 11 | entity-filters.spec.ts | — | Entity filters: type/name filtering on browse, co-occurrence, badges |
| 12 | wave1-cert-renew.spec.ts | — | Certification renewal: Renew button on cert/framework cards, dashboard links |
| 13 | wave1-dashboard-expiry.spec.ts | — | Dashboard expiry: ExpiringContentSection, ComplianceStatusSection, urgency badges |
| 14 | wave1-guide-sections.spec.ts | — | Guide sections: GuideSectionBanner on create page, match strength, dismiss |
| 15 | wave1-item-detail-dates.spec.ts | — | Item detail dates: ExpiryDateDisplay, TemporalReferencesSection, UK date format |
E2E Helpers
Section titled “E2E Helpers”Shared utilities in e2e/helpers/:
| File | Purpose |
|---|---|
dev-overlays.ts | Hide CopilotKit Web Inspector, stub /api/copilotkit/ requests, dismiss error banners |
responsive.ts | Viewport detection (isMobileViewport), header navigation (navigateViaHeader), search helpers |
data-factory.ts | Create test items (createTestItem), Q&A pairs (createTestQAPair), bids (createTestBid) |
selectors.ts | Shared selectors for nav, search, browse, and common UI components |
E2E Fixtures
Section titled “E2E Fixtures”Worker-scoped fixtures in e2e/fixtures/:
| File | Purpose |
|---|---|
index.ts | Main fixture export — extends Playwright test with authenticatedPage, viewerPage, workerData |
auth.ts | Authentication fixture — login with test user credentials |
supabase.ts | Supabase service client for data seeding |
test-data-fixture.ts | Worker-scoped data fixture — seeds content items, Q&A pairs, bids per worker |
test-data.ts | Test data definitions — IDs and content for seeded items |
Flow 0: Authentication
Section titled “Flow 0: Authentication”Preconditions: Dev server running (bun dev), valid Supabase user exists.
Spec: auth.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 0.1 | Navigate to http://localhost:3000 | Redirected to /login (unauthenticated) or home page (authenticated) | Page loads without errors |
| 0.2 | On /login, enter valid email, click “Continue” | Email accepted, method selection shown | ”Sign in with password” and “Send magic link” options visible |
| 0.3 | Click “Sign in with password”, enter password, click “Sign in” | Redirect to / (home page) | URL changes to /, dashboard content visible |
| 0.4 | Verify session persists across page navigation | Navigate to /browse, /bid, /settings — all load without re-auth | No redirect to /login |
| 0.5 | Test invalid credentials | Enter wrong password, click “Sign in” | Error message: “That email and password combination didn’t work. Please try again.” |
| 0.6 | Test magic link flow | Enter email, click “Continue”, then “Send magic link” | Success: heading “Check your email” with message “We sent a sign-in link to {email}” |
Error states:
- Empty email: HTML5 validation prevents submission
- Network error: Error message displayed
Flow 1: Home Page and Dashboard
Section titled “Flow 1: Home Page and Dashboard”Preconditions: Authenticated session, content items exist in database.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 1.1 | Navigate to / | Home page loads with hero search bar and dashboard sections | Reorient Me, Needs Attention, Active Bids, Content Health, Recent Activity sections render |
| 1.2 | Verify Reorient Me section | 3 sub-sections: “Needs your attention” (bid deadlines, expired content, pending reviews, quality flags, unread notifications), “Since you were away” (grouped team changes), “Pick up where you left off” (user’s recent work, max 3 items) | All sub-sections render with relevant data or empty states |
| 1.3 | Dismiss Reorient Me section | Click dismiss button | Section hides for current session, reappears on next visit |
| 1.4 | Verify Content Health strip | Freshness counts (Fresh/Aging/Stale/Expired), Active Bids count, Unread count | Numbers match DB reality |
| 1.5 | Verify Needs Attention section | Unverified items count with Review link, quality flags with Browse link | Links navigate to /review and /browse?quality_issues=true |
| 1.6 | Verify Active Bids section | Active bid cards with name, buyer, status, deadline, progress | At least one bid card if bids exist |
| 1.7 | Verify Recent Activity section | Activity feed with timestamped events | Events listed chronologically |
| 1.8 | Verify Expiring Content section | Items expiring within 30 days with urgency badges | Colour coding uses freshness semantic tokens |
| 1.9 | Verify Compliance Status section | Certification and framework summary cards with expiry badges | Cards show certification/framework/registration status |
| 1.10 | Click a Needs Attention link | Navigate to /review or /browse?quality_issues=true | Target page loads |
| 1.11 | Click an Active Bid card | Navigate to /bid/{id} | Bid detail page loads |
| 1.12 | Type a query in hero search bar, press Enter | Navigate to /search?q={query} | Search results page loads |
Flow 2: Content Browse and Search
Section titled “Flow 2: Content Browse and Search”Preconditions: Authenticated, content items exist across multiple domains.
Spec: browse-search.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 2.1 | Navigate to /browse | Browse page loads with content grid and filter controls | Grid renders, filter bar visible, item count shown |
| 2.2 | Switch from grid view to list view | Content displayed as list rows | View toggle works, items re-render |
| 2.3 | Switch back to grid view | Content displayed as grid cards | Toggle persists layout change |
| 2.4 | Apply domain filter (select a domain) | Grid filters to show only items in selected domain | Item count decreases, all visible items match domain |
| 2.5 | Apply content type filter | Grid filters further | Combined filters work correctly |
| 2.6 | Apply entity type filter | Grid filters to items mentioning entities of that type | Entity filter section expands, filter badge shown |
| 2.7 | Apply layer filter | Grid filters to items with selected layer | Layer badges match filter |
| 2.8 | Clear all filters | Full content list restored | Item count returns to unfiltered total |
| 2.9 | Use pagination (if >20 items) | Next page loads, different items shown | Page indicator updates |
| 2.10 | Click a content item | Navigate to /item/{id} | Item detail page loads |
| 2.11 | Navigate to /search directly | Search page loads with search bar | Empty state or prompt to search |
| 2.12 | Enter a search query (e.g., “project management”) | Search results appear with similarity scores | Results are relevant, similarity badges shown |
| 2.13 | Click a search result | Navigate to /item/{id} | Item detail page loads |
Flow 3: Item Detail and Editing
Section titled “Flow 3: Item Detail and Editing”Preconditions: Authenticated with editor role, at least one content item
exists. Spec: item-detail.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 3.1 | Navigate to /item/{id} for a known item | Detail page loads with title, metadata, content | Title, domain, content type, date all visible |
| 3.2 | Verify metadata display | Domain badge, content type icon, author, source, date, quality score badge | All metadata fields render correctly |
| 3.3 | Verify AI summary section | AI summary shown if available | Summary text visible or “No summary” placeholder |
| 3.4 | Verify related items section | Related items displayed at bottom | Cards shown with similarity scores |
| 3.5 | Verify breadcrumb navigation | Breadcrumb shows Browse link for articles, Library for Q&A | Correct parent link based on content type |
| 3.6 | Edit priority (set to “high”) | Priority selector updates | Priority persists after page refresh |
| 3.7 | Add item to a workspace | Workspace assignment updates | Workspace tag visible on item |
| 3.8 | Verify reader view | Content displayed in reader format | Reader HTML renders without broken layout |
| 3.9 | Verify expiry date display (if present) | ExpiryDateDisplay shows DD/MM/YYYY with urgency badge | Date format is UK English |
| 3.10 | Verify temporal references (if present) | Collapsible section with extracted dates | Dates show context type and confidence |
Flow 4: Bid Creation and Question Extraction
Section titled “Flow 4: Bid Creation and Question Extraction”Preconditions: Authenticated with editor role. A .docx or .pdf tender
document available locally. Spec: bid-pipeline.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 4.1 | Navigate to /bid | Bids list page loads | Page renders, “New Bid” button visible for editors |
| 4.2 | Click “New Bid” button | Bid creation dialog opens | Form with name, buyer, deadline fields |
| 4.3 | Fill in bid name “Test E2E Bid”, buyer “Test Corp”, deadline tomorrow | Form validates inputs | All fields accept input |
| 4.4 | Submit the form | Redirect to /bid/{new-id} | Bid detail page loads, state is “draft” |
| 4.5 | Verify bid header | Name, buyer, deadline, state badge all correct | Data matches what was entered |
| 4.6 | Verify tabs: Overview, Questions, Responses, Documents | All 4 tabs render and are clickable | Tab switching works |
| 4.7 | Click Documents tab | Documents section shown, upload area visible | TenderUpload component renders |
| 4.8 | Upload a .docx tender document | Upload progress shown, extraction begins | File accepted, processing indicator visible |
| 4.9 | After extraction completes | Question review dialog appears | Extracted questions listed with sections |
| 4.10 | Review extracted questions — confirm individual questions | Checkmarks toggle on/off per question | Individual question accept/reject works |
| 4.11 | Click “Confirm” to accept questions | Questions saved, dialog closes | Questions tab shows extracted questions |
| 4.12 | Switch to Questions tab | Questions listed with section grouping | Question text, word limits, categories visible |
| 4.13 | Add a manual question | Click “Add Question”, enter text, save | New question appears in list |
| 4.14 | Navigate back to /bid | Bids list shows the new bid | Bid card visible with correct name and state |
Error states:
- Upload invalid file type (e.g., .txt): Error message shown
- Upload empty file: Error message shown
- Create bid with empty name: Validation prevents submission
Flow 5: Bid Response Drafting
Section titled “Flow 5: Bid Response Drafting”Preconditions: Authenticated, bid exists with at least 3 confirmed
questions. ANTHROPIC_API_KEY set.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 5.1 | Navigate to /bid/{id} | Bid detail loads with questions | Questions tab accessible |
| 5.2 | Click “Match KB” button | Questions matched against knowledge base | Toast shows match count |
| 5.3 | Click “Draft All” button | Cost estimate dialog may appear | Drafting begins for unmatched questions |
| 5.4 | Wait for drafting to complete | Toast shows “Drafted N responses” | Response count updates |
| 5.5 | Navigate to /bid/{id}/session | CopilotKit session page loads | Chat interface and response panel visible |
| 5.6 | Use CopilotKit to draft a specific response | AI generates a response | Response text appears in editor |
| 5.7 | Review the response in the Tiptap editor | Rich text editor with response content | Text is editable, formatting preserved |
| 5.8 | Edit the response text | Text changes reflected in editor | Modifications persist |
| 5.9 | Approve the response | Response status changes to “approved” | Status indicator updates |
| 5.10 | Verify response versioning | Edit approved response and save | Version number increments |
Error states:
- Draft without API key: Clear error message
- Draft with no questions: Appropriate warning
Flow 6: Bid Export
Section titled “Flow 6: Bid Export”Preconditions: Bid exists with at least 2 approved responses.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 6.1 | Navigate to /bid/{id} | Bid detail loads | Export button visible in header |
| 6.2 | Click Export menu | Dropdown with “Export as Word” and “Export as Excel” | Both options visible |
| 6.3 | Click “Export as Word” | .docx file downloads | File downloads with bid name in filename |
| 6.4 | Open downloaded .docx | Document contains bid name, questions, and responses | All approved responses present, formatted correctly |
| 6.5 | Click “Export as Excel” | .xlsx file downloads | File downloads with bid name in filename |
| 6.6 | Open downloaded .xlsx | Spreadsheet contains questions and responses in columns | Data matches bid content |
Error states:
- Export bid with no responses: Warning or empty document generated
- Download fails: Error toast shown
Flow 7: Template Completion
Section titled “Flow 7: Template Completion”Preconditions: Authenticated, bid exists with confirmed questions and
approved responses. Python worker running
(PYTHONUNBUFFERED=1 python3 scripts/bid_worker.py).
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 7.1 | Navigate to /bid/{id}/templates | Templates page loads | Upload area visible, existing templates listed (if any) |
| 7.2 | Enter template name “Test Template” and description | Fields accept input | Name field required, description optional |
| 7.3 | Upload a .docx template file (drag-and-drop or click) | Upload progress shown | File accepted, template appears in list |
| 7.4 | Click “Analyse” on the uploaded template | Analysis job queued, progress shown | Status changes to “analysing” |
| 7.5 | Wait for analysis to complete | Template fields identified and listed | Status changes to “analysed”, field count shown |
| 7.6 | Click to review fields | Field review table opens | All identified fields listed with field text |
| 7.7 | Click “Auto-Map” to match fields to bid questions | Fields mapped to questions via text similarity | Mapping confidence shown, matched questions displayed |
| 7.8 | Review mappings — confirm correct ones (Enter key) | Field status changes to “confirmed” | Keyboard shortcut works |
| 7.9 | Reject incorrect mappings (r key) | Field status changes to “rejected” | Rejected fields visually distinct |
| 7.10 | Navigate fields with j/k keys | Selection moves up/down | Keyboard navigation works |
| 7.11 | Use bulk reject with checkboxes | Multiple fields rejected at once | Bulk action button works |
| 7.12 | Click “Fill Template” | Fill job queued, progress bar shown | Status changes to “filling” |
| 7.13 | Wait for fill to complete | Completion summary shown | Filled count, error count, truncation warnings |
| 7.14 | Download completed document | .docx file downloads | File downloads successfully |
| 7.15 | Open downloaded .docx | Responses filled in correct cells, formatting preserved | Content matches approved responses |
| 7.16 | Verify retry button on fill error | If fill fails, retry button shown | Button triggers new fill job |
Error states:
- Upload non-.docx file: Error message
- Upload password-protected .docx: Clear error (WP5)
- Analyse without Python worker: Job stays queued, timeout message
- Fill with no confirmed mappings: Validation prevents fill
Flow 8: Content Governance and Review
Section titled “Flow 8: Content Governance and Review”Preconditions: Authenticated with editor role, content items exist.
Spec: governance-review.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 8.1 | Navigate to /review | Review queue loads | Speed-review cards visible |
| 8.2 | Review a content item — click Approve | Item marked as reviewed | Card advances to next item |
| 8.3 | Review a content item — click Reject | Item marked for follow-up | Card advances to next item |
| 8.4 | Skip a content item | Item skipped, next item shown | Skip doesn’t change item status |
| 8.5 | Verify review stats | Stats bar shows reviewed/pending counts | Numbers update after each action |
| 8.6 | Navigate to /browse | Browse page loads | Freshness indicators visible on items |
| 8.7 | Check freshness badges | Items show fresh/aging/stale/expired status | Colour coding uses semantic freshness tokens |
| 8.8 | Navigate to /settings, Governance tab | Governance settings visible | Freshness thresholds configurable (admin only) |
Error states:
- Viewer role accessing
/review: Redirected to/browsewith notice - Empty review queue: Empty state message shown
Flow 9: Settings and Multi-User
Section titled “Flow 9: Settings and Multi-User”Preconditions: Authenticated with admin role. Specs: settings.spec.ts,
role-gating.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 9.1 | Navigate to /settings | Settings page loads with sidebar navigation | 7 sections visible (admin): Profile, Integrations, Taxonomy, Tags, Team, Governance, Activity. Non-admins see: Profile, Integrations only |
| 9.2 | Profile section | User profile info displayed | Email, display name, role badge, password change visible |
| 9.3 | Integrations section | MCP server connection details | Connection URL, auth instructions, connector status |
| 9.4 | Taxonomy section | Domain/subtopic configuration | Domain list with edit capability |
| 9.5 | Tags section | Tag management | Tag list with create/rename/merge |
| 9.6 | Team section (admin only) | User management interface | List of users with roles, invite button |
| 9.7 | Governance section (admin only) | Governance configuration | Freshness thresholds, review posture per domain |
| 9.8 | Activity section | Activity feed displayed | Recent actions listed chronologically |
| 9.9 | Invite a new user | Click invite, enter email, select role | Invitation dialog functional |
| 9.10 | Change a user’s role | Select new role from dropdown, confirm | Role updated, badge changes |
| 9.11 | Test appearance settings (site header) | Click gear icon in site header — toggle dark/light/system mode, accessibility switches | Theme changes instantly. Dyslexia-friendly, high contrast, large text switches available. Note: appearance is in site header dialog, NOT in Settings page |
Flow 10: Digest Generation
Section titled “Flow 10: Digest Generation”Preconditions: Authenticated, content items exist. ANTHROPIC_API_KEY set.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 10.1 | Navigate to /digest | Digest page loads | Period selector and generate button visible |
| 10.2 | Select period (e.g., “Last 7 days”) | Period selection updates | Dropdown reflects choice |
| 10.3 | Click “Generate Digest” | AI digest generation begins | Loading spinner shown |
| 10.4 | Wait for digest to complete | Digest content displayed | Summary, key themes, item references visible |
| 10.5 | Check digest history | Previous digests listed | Timestamps and periods shown |
Error states:
- Generate with no recent content: Appropriate message
- API error: Error toast shown
Flow 11: Workspaces
Section titled “Flow 11: Workspaces”Preconditions: Authenticated with editor role.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 11.1 | Navigate to /workspaces | Workspaces page loads | Workspace list or empty state |
| 11.2 | Create a new workspace | Click create, enter name and description | Workspace created, appears in list |
| 11.3 | View workspace detail | Click workspace card | Workspace detail with assigned items |
| 11.4 | Add items to workspace | Assign content items to workspace | Items appear in workspace view |
Flow 12: Q&A Library
Section titled “Flow 12: Q&A Library”Preconditions: Authenticated, Q&A pairs exist in database. Spec:
qa-library.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 12.1 | Navigate to /library | Q&A Library page loads | List of Q&A pairs visible with filter controls |
| 12.2 | Apply domain filter | List filters to selected domain | Item count decreases, all visible items match |
| 12.3 | Search within Q&A library | Results filtered by search text | Matching Q&A pairs shown |
| 12.4 | Click a Q&A pair | Detail view or inline expansion | Question and answer content visible |
| 12.5 | Copy a Q&A pair to a bid | Select bid target, confirm copy | Success confirmation, pair linked to bid |
Note: The Q&A Library uses @tanstack/react-virtual (window virtualiser).
With 173+ production Q&A pairs, items may be off-screen and require scrolling to
access.
Flow 13: Coverage Analysis
Section titled “Flow 13: Coverage Analysis”Preconditions: Authenticated, content items exist across multiple taxonomy
domains. Spec: coverage-page.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 13.1 | Navigate to /coverage | Coverage page loads | Domain coverage overview visible |
| 13.2 | Review domain coverage | Each domain shows item counts and freshness distribution | Data matches DB reality |
| 13.3 | Identify gaps | Domains with low or no coverage highlighted | Gap indicators visible |
Flow 14: Appearance and Accessibility Settings
Section titled “Flow 14: Appearance and Accessibility Settings”Preconditions: Authenticated.
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 14.1 | Click gear icon in site header | Appearance settings dialog opens | Theme and accessibility options visible |
| 14.2 | Toggle dark/light/system mode | Theme changes instantly | Page re-renders with correct theme |
| 14.3 | Enable dyslexia-friendly font | Font changes to Atkinson Hyperlegible or similar | Text re-renders |
| 14.4 | Enable high contrast mode | Contrast increases across all elements | Visual change noticeable |
| 14.5 | Enable large text | Text size increases | Layout adjusts to accommodate |
| 14.6 | Close and reopen dialog | Settings persist | Previously selected options still active |
Flow 15: Layer Suggestion
Section titled “Flow 15: Layer Suggestion”Preconditions: Authenticated with editor role, layer vocabulary configured.
Spec: layer-suggestion.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 15.1 | Navigate to /item/new | Create content form loads | Form fields visible including domain, content type |
| 15.2 | Create a new content item | After saving, LayerSuggestionBanner appears | Banner shows as role="region" with aria-label “Layer suggestion” |
| 15.3 | Accept suggested layer | Layer assigned to item | Banner dismissed |
| 15.4 | Navigate to /browse, check layer filter | Layer filter available in filter panel | Filter shows layer options from layer_vocabulary |
| 15.5 | Apply layer filter | Browse results filtered by layer | Layer badges visible on content cards |
Flow 16: Entity Filters
Section titled “Flow 16: Entity Filters”Preconditions: Authenticated, content items with entity mentions exist.
Spec: entity-filters.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 16.1 | Navigate to /browse, open filter panel | Filter panel (Sheet dialog) opens | Entity Type and Entities sections visible (collapsed by default) |
| 16.2 | Expand Entity Type section | Entity type buttons with counts shown | Buttons have aria-pressed state |
| 16.3 | Select an entity type | Browse results filtered | Filter badge appears, item count changes |
| 16.4 | Clear entity type filter | Results restored | Filter badge removed |
| 16.5 | Navigate to /item/{id} for item with entities | Entity badges displayed | Badge colours match entity type tokens |
Flow 17: Certification and Compliance
Section titled “Flow 17: Certification and Compliance”Preconditions: Authenticated, entity_mentions with certification metadata
exist. Specs: wave1-cert-renew.spec.ts, wave1-dashboard-expiry.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 17.1 | Navigate to / (dashboard) | Compliance Status section renders | Certification and framework summary cards visible |
| 17.2 | Verify expiry badges on certifications | Expiry status shown (valid/expiring_soon/expired) | Badge colours use freshness semantic tokens |
| 17.3 | Click “Renew” on expiring certification | Navigates to item detail with renewal_entity query parameter | Item detail page loads |
| 17.4 | Verify Expiring Content section | Items expiring within 30 days listed with urgency | Urgency colour coding visible |
Flow 18: Guide Sections and Date Features
Section titled “Flow 18: Guide Sections and Date Features”Preconditions: Authenticated with editor role, guides configured. Specs:
wave1-guide-sections.spec.ts, wave1-item-detail-dates.spec.ts
| # | Step | Expected Outcome | Pass/Fail Criteria |
|---|---|---|---|
| 18.1 | Navigate to /item/new, create content | GuideSectionBanner may appear after creation | Banner shows as role="region" with matched guide sections |
| 18.2 | Verify guide section links | Section links point to /guide/{slug}#{sectionId} | Match strength badges visible |
| 18.3 | Navigate to item with expiry_date | ExpiryDateDisplay shows in DD/MM/YYYY format | Urgency badge uses freshness tokens |
| 18.4 | Verify temporal references section | Collapsible section with extracted dates | Uses aria-expanded and aria-controls |
Cross-Cutting Concerns
Section titled “Cross-Cutting Concerns”Accessibility (test across all flows)
Section titled “Accessibility (test across all flows)”| # | Check | Pass/Fail Criteria |
|---|---|---|
| A.1 | Keyboard navigation | All interactive elements reachable via Tab |
| A.2 | Focus indicators | Visible focus ring on all focusable elements |
| A.3 | Screen reader landmarks | Semantic HTML (headings, nav, main, sections) |
| A.4 | Colour contrast | Text meets WCAG 2.1 AA (4.5:1 ratio) |
| A.5 | No colour-alone meaning | All status indicators have text or icon backup |
| A.6 | Skip link | Skip to main content link available at page top |
Responsive Design
Section titled “Responsive Design”| # | Check | Pass/Fail Criteria |
|---|---|---|
| R.1 | Mobile viewport (375px / Pixel 5) | All pages usable, no horizontal scroll. Hamburger menu for navigation |
| R.2 | Tablet viewport (768px) | Layout adapts, grids collapse appropriately. Settings sidebar becomes Sheet drawer |
| R.3 | Desktop viewport (1440px) | Full layout, max-width containers centred |
Error Handling
Section titled “Error Handling”| # | Check | Pass/Fail Criteria |
|---|---|---|
| E.1 | Network disconnect | Toast errors, no crashes |
| E.2 | Invalid route | 404 page displayed |
| E.3 | Unauthorised access | Redirect to login or appropriate error |
| E.4 | API errors | User-friendly error messages, no raw stack traces |
Page Coverage Matrix
Section titled “Page Coverage Matrix”| Page | Covered By |
|---|---|
/ (home) | Flow 1, Flow 17, Flow 18 |
/login | Flow 0 |
/browse | Flow 2, Flow 16 |
/search | Flow 2 |
/item/[id] | Flow 3, Flow 17, Flow 18 |
/item/new | Flow 15, Flow 18 |
/bid | Flow 4 |
/bid/[id] | Flow 4, 5, 6 |
/bid/[id]/session | Flow 5 |
/bid/[id]/templates | Flow 7 |
/review | Flow 8 |
/settings | Flow 9 |
/digest | Flow 10 |
/workspaces | Flow 11 |
/library | Flow 12 |
/coverage | Flow 13 |
/auth/callback | Flow 0 (implicit) |
/oauth/consent | Flow 0 (implicit, MCP OAuth) |
| Site header (appearance) | Flow 14 |
Running E2E Tests
Section titled “Running E2E Tests”# Install Playwright browsers (first time only)bunx playwright install chromium
# Run all E2E specs (starts dev server automatically)bunx playwright test
# Run a specific specbunx playwright test e2e/tests/browse-search.spec.ts
# Run Wave 1 specs onlybunx playwright test --grep @wave1
# Run with UI mode for debuggingbunx playwright test --ui
# View test reportbunx playwright show-reportImportant: E2E tests need dangerouslyDisableSandbox: true in Claude Code
due to port 3000 binding. The NEXT_PUBLIC_E2E=true environment variable is set
automatically by playwright.config.ts to disable CopilotKit during tests.
Generated: Session 46, 5 March 2026. Updated: Session 69b, 9 March 2026. Updated: 23/03/2026 (S108).