Browse documentation

Test Specs

RankFlow AI — Test Specification: User Dashboard UI

- 3.1 /dashboard — Home Overview

docs/test-specs/TEST-user-dashboard-ui.md
On this page

Version: 1.0.0
Date: 2026-06-13
Scope: All /dashboard/* routes, shell components, shared UI primitives, role-based access, responsive behavior, and content approval workflows.
Source Spec: docs/specs/user-dashboard-ui.md
Test Plan: docs/test-plan.md Section 3


1. Test Taxonomy & Tooling#

Category Tooling File Pattern Purpose
Unit Vitest + React Testing Library src/__tests__/unit/**/*.test.tsx Component rendering, props, state
Integration Vitest + MSW + tRPC test client src/__tests__/integration/**/*.test.ts Router + data layer
E2E Playwright e2e/dashboard/**/*.spec.ts Critical user flows
Visual Regression Playwright + Argos e2e/visual/**/*.spec.ts Pixel-perfect UI gates
Accessibility Playwright + axe-core e2e/a11y/**/*.spec.ts WCAG 2.1 AA compliance

2. Shell & Layout Tests#

2.1 ClientLayout (src/app/(client)/layout.tsx)#

Unit Tests#

Test Input Expected Output File
renders-with-auth authSession with CLIENT role Renders DashboardShell + children src/__tests__/unit/layout/ClientLayout.test.tsx
redirects-unauthenticated authSession = null Redirects to /login src/__tests__/unit/layout/ClientLayout.test.tsx
resolves-practice practiceId in session Calls practice.get and passes to context src/__tests__/unit/layout/ClientLayout.test.tsx
shows-practice-switcher User has 2+ practices PracticeSwitcher visible in sidebar src/__tests__/unit/layout/ClientLayout.test.tsx
hides-practice-switcher User has 1 practice PracticeSwitcher not rendered src/__tests__/unit/layout/ClientLayout.test.tsx

Integration Tests#

Test Setup Action Assertion File
layout-data-fetch DB has 1 practice + 3 locations Render layout with session practice.get resolves; no 404 src/__tests__/integration/layout/ClientLayout.test.ts
layout-invalid-practice Session practiceId not in DB Render layout Redirects to /onboarding src/__tests__/integration/layout/ClientLayout.test.ts

Success Criteria (Binary)#

  • SC-LAYOUT-01: Authenticated users see dashboard shell; unauthenticated redirect to /login.
  • SC-LAYOUT-02: Practice context is resolved and propagated to all children.
  • SC-LAYOUT-03: Practice switcher appears only when user has >1 practice.
  • SC-LAYOUT-04: Invalid practice ID in session triggers onboarding redirect.

Agent Context (Pre-conditions)#

  • Required DB state: User with CLIENT role, linked Practice with ACTIVE status.
  • Required env vars: NEXTAUTH_SECRET, NEXTAUTH_URL.
  • Required external mocks: None.

Verification Commands#

# Unit tests
pnpm test:unit -- src/__tests__/unit/layout/ClientLayout.test.tsx

# Integration tests
pnpm test:integration -- src/__tests__/integration/layout/ClientLayout.test.ts

2.2 DashboardSidebar (src/components/dashboard/Sidebar.tsx)#

Unit Tests#

Test Input Expected Output File
renders-nav-groups Standard props 5 nav groups visible: Marketing, Website, Analytics, Content, Account src/__tests__/unit/components/DashboardSidebar.test.tsx
marks-active-route Current path = /dashboard/gbp "GBP" nav item has aria-current="page" src/__tests__/unit/components/DashboardSidebar.test.tsx
collapsible-on-tablet isCollapsed = true Width reduces to 64px; icons only src/__tests__/unit/components/DashboardSidebar.test.tsx
toggle-collapse Click collapse button onToggle called; aria-expanded toggles src/__tests__/unit/components/DashboardSidebar.test.tsx
practice-switcher 2 practices Dropdown shows both; selecting updates context src/__tests__/unit/components/DashboardSidebar.test.tsx

Interaction Tests#

Test Action Expected Result File
nav-click Click "Social" nav item Router navigates to /dashboard/social src/__tests__/unit/components/DashboardSidebar.test.tsx
keyboard-nav Press Tab through nav items Focus ring visible; Enter triggers navigation src/__tests__/unit/components/DashboardSidebar.test.tsx
mobile-drawer Viewport < 768px; click hamburger Sidebar slides in as overlay; backdrop clickable e2e/dashboard/sidebar-mobile.spec.ts

Success Criteria (Binary)#

  • SC-SIDEBAR-01: All 10 nav items render with correct labels and icons.
  • SC-SIDEBAR-02: Active route is visually highlighted and accessible (aria-current).
  • SC-SIDEBAR-03: Collapse/expand toggles layout width and persists in localStorage.
  • SC-SIDEBAR-04: Practice switcher updates active practice context on selection.
  • SC-SIDEBAR-05: Mobile drawer opens/closes with backdrop and trap focus.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with ACTIVE status.
  • Required env vars: None.
  • Required external mocks: next/navigation mock for router.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/components/DashboardSidebar.test.tsx
pnpm test:e2e -- e2e/dashboard/sidebar-mobile.spec.ts

2.3 DashboardHeader (src/components/dashboard/Header.tsx)#

Unit Tests#

Test Input Expected Output File
renders-breadcrumbs Path = /dashboard/gbp/posts Breadcrumbs: Dashboard > GBP > Posts src/__tests__/unit/components/DashboardHeader.test.tsx
notification-bell 3 unread notifications Badge shows "3"; click opens dropdown src/__tests__/unit/components/DashboardHeader.test.tsx
user-menu User name = "Dr. Sharma" Avatar + name visible; click opens menu src/__tests__/unit/components/DashboardHeader.test.tsx
logout Click logout in user menu Calls signOut from next-auth/react src/__tests__/unit/components/DashboardHeader.test.tsx

Success Criteria (Binary)#

  • SC-HEADER-01: Breadcrumbs render correctly for all nested routes (≤3 levels).
  • SC-HEADER-02: Notification bell displays unread count and opens dropdown.
  • SC-HEADER-03: User menu shows name/avatar and logout triggers signOut.
  • SC-HEADER-04: Header is sticky on scroll (position: sticky; top: 0).

Verification Commands#

pnpm test:unit -- src/__tests__/unit/components/DashboardHeader.test.tsx

3. Page-Level Test Specifications#


3.1 /dashboard — Home Overview#

Unit Tests#

Test Input Expected Output File
renders-stat-cards 6 KPIs from tRPC 6 StatCard components render with correct values src/__tests__/unit/pages/DashboardHomePage.test.tsx
loading-state Queries loading LoadingSkeleton renders instead of cards src/__tests__/unit/pages/DashboardHomePage.test.tsx
empty-state 0 posts, 0 reviews EmptyState for each section with CTA src/__tests__/unit/pages/DashboardHomePage.test.tsx
recent-gbp-posts 3 posts from API Last 3 posts with status badges src/__tests__/unit/pages/DashboardHomePage.test.tsx
latest-reviews 5 reviews from API Last 5 reviews with star rating + reply status src/__tests__/unit/pages/DashboardHomePage.test.tsx
quick-actions Standard props "Create Post", "Add Location", "View Report" buttons visible src/__tests__/unit/pages/DashboardHomePage.test.tsx
seo-score-color Score = 45 Badge color = red (critical) src/__tests__/unit/pages/DashboardHomePage.test.tsx
seo-score-color Score = 85 Badge color = green (good) src/__tests__/unit/pages/DashboardHomePage.test.tsx

Interaction Tests#

Test Action Expected Result File
quick-action-create-post Click "Create Post" Navigates to /dashboard/gbp/posts?create=true src/__tests__/unit/pages/DashboardHomePage.test.tsx
quick-action-view-report Click "View Report" Navigates to /dashboard/reports src/__tests__/unit/pages/DashboardHomePage.test.tsx
review-click Click a review row Navigates to /dashboard/gbp/reviews?id=reviewId src/__tests__/unit/pages/DashboardHomePage.test.tsx
post-click Click a post row Navigates to /dashboard/gbp/posts?id=postId src/__tests__/unit/pages/DashboardHomePage.test.tsx

E2E Tests#

Flow Steps Expected End State File
home-overview-flow 1. Login as CLIENT. 2. Navigate to /dashboard. 3. Wait for KPIs. All 6 stat cards visible with non-loading values. e2e/dashboard/home-overview.spec.ts

Success Criteria (Binary)#

  • SC-HOME-01: All 6 stat cards render with correct labels, values, and trend indicators.
  • SC-HOME-02: Recent GBP Posts section shows last 3 posts with status badges.
  • SC-HOME-03: Latest Reviews section shows last 5 reviews with reply status.
  • SC-HOME-04: Upcoming Social section shows next 5 scheduled posts.
  • SC-HOME-05: Citation Health section displays NAP consistency percentage.
  • SC-HOME-06: Quick Action buttons navigate to correct routes.
  • SC-HOME-07: Loading state shows skeletons; empty state shows CTAs.
  • SC-HOME-08: SEO score badge color changes based on score range (0-49 red, 50-79 yellow, 80-100 green).

Agent Context (Pre-conditions)#

  • Required DB state: Practice with related RankTracking, Citation, Review, SocialPost, Report records.
  • Required env vars: None.
  • Required external mocks: msw handlers for practice.get, gbp.listPosts, review.list, social.listPosts, citation.list, report.list.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/DashboardHomePage.test.tsx
pnpm test:e2e -- e2e/dashboard/home-overview.spec.ts

3.2 /dashboard/gbp — GBP Overview (and sub-routes)#

Unit Tests — Overview Tab#

Test Input Expected Output File
gbp-status-card Connected account, 2 locations Shows "Connected", email, location count, last sync src/__tests__/unit/pages/GbpOverviewPage.test.tsx
sync-now-button Click "Sync Now" Calls gbp.sync mutation; shows loading spinner src/__tests__/unit/pages/GbpOverviewPage.test.tsx
reconnect-button Click "Reconnect" Calls gbp.getAuthUrl; opens OAuth popup src/__tests__/unit/pages/GbpOverviewPage.test.tsx
posts-this-week 3 published posts Card shows "3 published" + "View all" link src/__tests__/unit/pages/GbpOverviewPage.test.tsx
reviews-summary 12 new, 2 unreplied Card shows "12 new (2 unr.)" + "Reply" link src/__tests__/unit/pages/GbpOverviewPage.test.tsx

Unit Tests — Posts Tab#

Test Input Expected Output File
calendar-view 5 posts across 2 weeks Calendar grid shows posts on correct dates src/__tests__/unit/pages/GbpPostsPage.test.tsx
list-view-toggle Click "List" tab Switches from calendar to table view src/__tests__/unit/pages/GbpPostsPage.test.tsx
create-post-modal Click "Create Post" Modal opens with form + AI assist button src/__tests__/unit/pages/GbpPostsPage.test.tsx
edit-scheduled-post Click edit on scheduled post Modal opens pre-filled; save calls gbp.updatePost src/__tests__/unit/pages/GbpPostsPage.test.tsx
delete-post-confirm Click delete; confirm dialog Calls gbp.deletePost after confirmation src/__tests__/unit/pages/GbpPostsPage.test.tsx
ai-assist-generates Click AI assist in modal Calls ai.generateGbpPost; fills text area src/__tests__/unit/pages/GbpPostsPage.test.tsx

Unit Tests — Reviews Tab#

Test Input Expected Output File
review-list 10 reviews Table renders star, comment (truncated), date src/__tests__/unit/pages/GbpReviewsPage.test.tsx
reply-inline Click "Reply" on review Text area appears + AI generate button src/__tests__/unit/pages/GbpReviewsPage.test.tsx
ai-reply-generates Click AI generate Calls ai.generateReviewReply; fills text area src/__tests__/unit/pages/GbpReviewsPage.test.tsx
filter-unreplied Select "Unreplied" filter Only unreplied reviews visible src/__tests__/unit/pages/GbpReviewsPage.test.tsx
filter-negative Select "Negative" filter Only 1-2 star reviews visible src/__tests__/unit/pages/GbpReviewsPage.test.tsx
bulk-reply Select 3 reviews; click "Bulk Reply" Calls gbp.bulkReply with selected IDs src/__tests__/unit/pages/GbpReviewsPage.test.tsx

Unit Tests — Insights Tab#

Test Input Expected Output File
views-chart 30 days of data Line chart renders with Search + Maps series src/__tests__/unit/pages/GbpInsightsPage.test.tsx
actions-breakdown Action data Bar chart renders Website, Phone, Directions, Booking src/__tests__/unit/pages/GbpInsightsPage.test.tsx
search-queries-table Top 20 queries Table renders query + count + trend src/__tests__/unit/pages/GbpInsightsPage.test.tsx
photo-views Photo engagement data Bar chart or metric cards render src/__tests__/unit/pages/GbpInsightsPage.test.tsx
post-engagement Post data Table with views, clicks per post src/__tests__/unit/pages/GbpInsightsPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
gbp-post-lifecycle 1. Go to /dashboard/gbp/posts. 2. Create post. 3. Schedule. 4. Edit. 5. Delete. Post deleted; list updated. e2e/dashboard/gbp-post-lifecycle.spec.ts
gbp-review-reply 1. Go to /dashboard/gbp/reviews. 2. Filter unreplied. 3. Click Reply. 4. Type message. 5. Submit. Review marked as replied; success toast. e2e/dashboard/gbp-review-reply.spec.ts

Success Criteria (Binary)#

  • SC-GBP-01: Overview tab shows connected status, location count, and sync controls.
  • SC-GBP-02: Posts tab supports calendar and list view with toggle.
  • SC-GBP-03: Create Post modal opens, validates, and submits to gbp.createPost.
  • SC-GBP-04: Edit Post works for scheduled posts only; published posts are read-only.
  • SC-GBP-05: Delete Post requires confirmation via ConfirmDialog.
  • SC-GBP-06: AI Assist button in post modal calls AI service and populates content.
  • SC-GBP-07: Reviews tab lists all reviews with star, comment, date.
  • SC-GBP-08: Inline reply opens text area; AI generate creates HIPAA-safe reply.
  • SC-GBP-09: Filters (All / Unreplied / Negative / Positive) correctly filter list.
  • SC-GBP-10: Bulk Reply selects multiple reviews and calls gbp.bulkReply.
  • SC-GBP-11: Insights tab renders 4 charts without console errors.
  • SC-GBP-12: Sync Now triggers gbp.sync and shows success/error toast.
  • SC-GBP-13: Reconnect opens Google OAuth flow.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with GbpAccount (connected), GbpLocation (2), GbpPost (5), GbpReview (10), GbpInsight (30 days).
  • Required env vars: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET.
  • Required external mocks: msw for Google OAuth, GBP API, AI service.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/GbpOverviewPage.test.tsx
pnpm test:unit -- src/__tests__/unit/pages/GbpPostsPage.test.tsx
pnpm test:unit -- src/__tests__/unit/pages/GbpReviewsPage.test.tsx
pnpm test:unit -- src/__tests__/unit/pages/GbpInsightsPage.test.tsx
pnpm test:e2e -- e2e/dashboard/gbp-post-lifecycle.spec.ts
pnpm test:e2e -- e2e/dashboard/gbp-review-reply.spec.ts

3.3 /dashboard/social — Social Media#

Unit Tests#

Test Input Expected Output File
account-cards 3 connected accounts (FB, IG, X) 3 cards with logo, handle, follower count, status src/__tests__/unit/pages/SocialOverviewPage.test.tsx
disconnect-account Click "Disconnect" on FB card ConfirmDialog opens; confirm calls social.disconnect src/__tests__/unit/pages/SocialOverviewPage.test.tsx
compose-post Text + media in compose area Character counter updates; preview renders src/__tests__/unit/pages/SocialOverviewPage.test.tsx
platform-select Toggle FB and IG on Post will publish to both platforms src/__tests__/unit/pages/SocialOverviewPage.test.tsx
schedule-picker Select date/time + timezone ISO string formatted correctly; past dates blocked src/__tests__/unit/pages/SocialOverviewPage.test.tsx
preview-panel Post content + platform Preview shows how post looks on FB, IG, X src/__tests__/unit/pages/SocialOverviewPage.test.tsx
queue-list 5 upcoming posts Queue renders with scheduled time + platform icons src/__tests__/unit/pages/SocialOverviewPage.test.tsx
history-list 10 past posts History renders with published time + engagement src/__tests__/unit/pages/SocialOverviewPage.test.tsx
hashtag-suggest Type "#dental" AI suggests hashtags; click inserts into text src/__tests__/unit/pages/SocialOverviewPage.test.tsx

Interaction Tests#

Test Action Expected Result File
post-now Fill compose; click "Post Now" Calls social.createPost; toast success; queue updates src/__tests__/unit/pages/SocialOverviewPage.test.tsx
schedule-post Fill compose; pick future time; click "Schedule" Calls social.schedulePosts; appears in queue src/__tests__/unit/pages/SocialOverviewPage.test.tsx
media-upload Select 2 images Thumbnails appear; max 4 images enforced src/__tests__/unit/pages/SocialOverviewPage.test.tsx
queue-drag-reorder Drag queue item New order persisted via social.reorderQueue src/__tests__/unit/pages/SocialOverviewPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
social-schedule-flow 1. Connect FB account (mocked). 2. Compose post. 3. Select FB. 4. Schedule for tomorrow. 5. View queue. Post visible in queue with correct time. e2e/dashboard/social-schedule.spec.ts

Success Criteria (Binary)#

  • SC-SOCIAL-01: Account cards show platform, handle, follower count, and connection status.
  • SC-SOCIAL-02: Disconnect requires confirmation and removes account from UI.
  • SC-SOCIAL-03: Compose area supports text, media upload (≤4 images), and hashtag suggestions.
  • SC-SOCIAL-04: Platform toggle determines which accounts receive the post.
  • SC-SOCIAL-05: Date/time picker blocks past dates and respects timezone.
  • SC-SOCIAL-06: Preview panel renders platform-specific post previews.
  • SC-SOCIAL-07: Queue shows upcoming posts in chronological order.
  • SC-SOCIAL-08: History shows past posts with engagement metrics.
  • SC-SOCIAL-09: "Post Now" publishes immediately; "Schedule" adds to queue.
  • SC-SOCIAL-10: Media upload validates file type (jpg, png, gif, mp4) and max size (10MB).

Agent Context (Pre-conditions)#

  • Required DB state: Practice with SocialAccount (3), SocialPost (15 upcoming + 10 past).
  • Required env vars: META_APP_ID, TWITTER_CLIENT_ID.
  • Required external mocks: msw for Meta Graph API, Twitter API, AI hashtag service.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/SocialOverviewPage.test.tsx
pnpm test:e2e -- e2e/dashboard/social-schedule.spec.ts

3.4 /dashboard/citations — Citation Network#

Unit Tests#

Test Input Expected Output File
progress-card 26/30 live, 87% Progress bar at 87%; counts: Verified 26, Pending 2, Failed 2 src/__tests__/unit/pages/CitationsPage.test.tsx
directory-table 30 directories Table with logo, name, status, NAP match, URL, last checked src/__tests__/unit/pages/CitationsPage.test.tsx
status-badges Live / Pending / Failed / Needs Update Each status renders correct color badge via StatusBadge src/__tests__/unit/pages/CitationsPage.test.tsx
nap-match-check All match vs mismatch ✅ shown when match; ❌ with tooltip when mismatch src/__tests__/unit/pages/CitationsPage.test.tsx
screenshot-thumbnail Thumbnail URL Image renders; click opens lightbox modal src/__tests__/unit/pages/CitationsPage.test.tsx
submit-new-directory Click "Submit to New Directory" Opens modal with directory selector; submit calls citation.submit src/__tests__/unit/pages/CitationsPage.test.tsx
re-verify-nap Click "Re-verify NAP" Calls citation.verifyNap; refreshes table src/__tests__/unit/pages/CitationsPage.test.tsx
download-report Click "Download Citation Report" Triggers CSV download with correct filename src/__tests__/unit/pages/CitationsPage.test.tsx
mismatch-details Click ❌ on NAP match Modal opens showing expected vs actual NAP fields src/__tests__/unit/pages/CitationsPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
citation-submission-flow 1. Go to /dashboard/citations. 2. Click "Submit to New Directory". 3. Select Justdial. 4. Submit. 5. Verify table update. New directory shows "Pending" status. e2e/dashboard/citation-submit.spec.ts

Success Criteria (Binary)#

  • SC-CITATIONS-01: Progress card shows accurate percentage and live/pending/failed counts.
  • SC-CITATIONS-02: Directory table renders 30 rows with all columns.
  • SC-CITATIONS-03: Status badges use correct semantic colors (green/yellow/red/blue).
  • SC-CITATIONS-04: NAP match shows ✅ or ❌ with clickable mismatch details modal.
  • SC-CITATIONS-05: Screenshot thumbnail opens lightbox on click.
  • SC-CITATIONS-06: Submit to new directory opens modal and calls citation.submit.
  • SC-CITATIONS-07: Re-verify NAP refreshes all rows and updates status.
  • SC-CITATIONS-08: Download report generates CSV with correct headers and data.
  • SC-CITATIONS-09: Table supports sorting by Directory, Status, and Last Checked.
  • SC-CITATIONS-10: Table supports filtering by status (Live, Pending, Failed, Needs Update).

Agent Context (Pre-conditions)#

  • Required DB state: Practice with 30 Citation records (mix of statuses), Directory (30).
  • Required env vars: FIRECRAWL_API_KEY.
  • Required external mocks: msw for Firecrawl NAP verification, directory submission APIs.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/CitationsPage.test.tsx
pnpm test:e2e -- e2e/dashboard/citation-submit.spec.ts

3.5 /dashboard/profile — Directory Profile#

Unit Tests#

Test Input Expected Output File
preview-panel directoryProfileUrl = https://rankflow.in/clinics/kochi/<directorySlug> Iframe renders with correct URL; device toggle visible src/__tests__/unit/pages/SitePreviewPage.test.tsx
device-toggle Click "Mobile" Iframe width changes to 375px; no horizontal scroll src/__tests__/unit/pages/SitePreviewPage.test.tsx
editor-panel Standard props All 7 sections (Hero, About, Services, Testimonials, FAQ, Contact, CTA) listed src/__tests__/unit/pages/SitePreviewPage.test.tsx
hero-edit Edit title, subtitle, CTA Calls directoryProfile.updateSection with new values; preview updates src/__tests__/unit/pages/SitePreviewPage.test.tsx
image-uploader Select new doctor photo ImageUploader handles file; preview updates after upload src/__tests__/unit/pages/SitePreviewPage.test.tsx
template-selector Select "Dental Clean" Calls directoryProfile.setTemplate; preview reloads with new template src/__tests__/unit/pages/SitePreviewPage.test.tsx
color-picker Change primary color Color swatch updates; preview reflects new color src/__tests__/unit/pages/SitePreviewPage.test.tsx
font-selector Select "Inter" Font family updates in preview src/__tests__/unit/pages/SitePreviewPage.test.tsx
directory-profile-url Input www.clinic.com Validates DNS; shows status indicator src/__tests__/unit/pages/SitePreviewPage.test.tsx
publish-toggle Toggle "Publish" on Calls directoryProfile.publish; site becomes live src/__tests__/unit/pages/SitePreviewPage.test.tsx
unpublish-toggle Toggle "Publish" off Calls directoryProfile.unpublish; site shows 404/under construction src/__tests__/unit/pages/SitePreviewPage.test.tsx
auto-update-toggle Toggle "Auto-update" on Setting persisted; badge shows "Auto" src/__tests__/unit/pages/SitePreviewPage.test.tsx

Interaction Tests#

Test Action Expected Result File
preview-refresh Edit hero title; click "Refresh Preview" Iframe reloads with new content src/__tests__/unit/pages/SitePreviewPage.test.tsx
section-collapse Click "Services" header Section expands/collapses with accordion animation src/__tests__/unit/pages/SitePreviewPage.test.tsx
rich-text-editor Use RichTextEditor in About section Content saves HTML; preview renders HTML safely src/__tests__/unit/pages/SitePreviewPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
site-edit-publish 1. Go to /dashboard/profile. 2. Edit hero title. 3. Change primary color. 4. Publish. 5. Visit live URL. Live site shows new title and color. e2e/dashboard/profile-edit-publish.spec.ts

Success Criteria (Binary)#

  • SC-SITE-01: Preview panel renders iframe with practice URL and device toggle (Desktop/Tablet/Mobile).
  • SC-SITE-02: Editor panel lists all 7 editable sections with collapsible accordions.
  • SC-SITE-03: Hero section edits (title, subtitle, CTA, background image) save and reflect in preview.
  • SC-SITE-04: Image uploader validates file type (jpg, png, webp) and max size (5MB).
  • SC-SITE-05: Profile template changes layout and preview reloads.
  • SC-SITE-06: Color picker updates primary color in preview within 1 second.
  • SC-SITE-07: Font selector changes font family in preview.
  • SC-SITE-08: Directory profile URL input validates format and shows DNS/directory path status.
  • SC-SITE-09: Publish toggle calls directoryProfile.publish; unpublish calls directoryProfile.unpublish.
  • SC-SITE-10: Auto-update toggle persists and shows status badge.
  • SC-SITE-11: Rich text editor in About section renders safe HTML (sanitized).
  • SC-SITE-12: Mobile device toggle sets iframe width to 375px; tablet to 768px; desktop to 100%.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with DirectoryProfile record (template, sections, settings).
  • Required env vars: NEXT_PUBLIC_SITE_DOMAIN, AWS_S3_BUCKET.
  • Required external mocks: msw for S3 upload, DNS validation API.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/SitePreviewPage.test.tsx
pnpm test:e2e -- e2e/dashboard/profile-edit-publish.spec.ts

3.6 /dashboard/reports — Reports#

Unit Tests#

Test Input Expected Output File
report-cards 12 monthly reports Grid of cards with month, year, overall score, category scores src/__tests__/unit/pages/ReportsPage.test.tsx
score-breakdown Report with GBP=82, CIT=75, REV=90, RNK=65 4 mini-cards with correct scores and colors src/__tests__/unit/pages/ReportsPage.test.tsx
view-pdf Click "View PDF" PDF viewer modal opens with correct URL src/__tests__/unit/pages/ReportsPage.test.tsx
email-report Click "Email" Opens email dialog with practice email pre-filled; send calls report.email src/__tests__/unit/pages/ReportsPage.test.tsx
download-report Click "Download" Triggers PDF download with filename Report_YYYY_MM.pdf src/__tests__/unit/pages/ReportsPage.test.tsx
generate-new-report Click "Generate Report" Calls report.generate; new card appears with loading state src/__tests__/unit/pages/ReportsPage.test.tsx
empty-reports 0 reports EmptyState with "Generate your first report" CTA src/__tests__/unit/pages/ReportsPage.test.tsx
report-score-color Score 78 Mini-cards color-coded: 82 green, 75 yellow, 90 green, 65 red src/__tests__/unit/pages/ReportsPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
report-generate-view 1. Go to /dashboard/reports. 2. Click "Generate Report". 3. Wait for completion. 4. Click "View PDF". PDF viewer opens with generated report. e2e/dashboard/report-generate.spec.ts

Success Criteria (Binary)#

  • SC-REPORTS-01: Report cards render month, year, overall score, and 4 category mini-scores.
  • SC-REPORTS-02: Category scores use color coding (≥80 green, 50-79 yellow, <50 red).
  • SC-REPORTS-03: View PDF opens modal with embedded PDF viewer or iframe.
  • SC-REPORTS-04: Email Report opens dialog and calls report.email with validated address.
  • SC-REPORTS-05: Download triggers PDF file download with correct filename.
  • SC-REPORTS-06: Generate Report creates new card with loading → success state transition.
  • SC-REPORTS-07: Empty state shows CTA when no reports exist.
  • SC-REPORTS-08: Reports sorted by date descending (newest first).

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Report records (12 monthly), RankTracking, Citation, Review, GbpInsight.
  • Required env vars: PDF_SERVICE_URL or Puppeteer config.
  • Required external mocks: msw for PDF generation service, email service (Resend).

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/ReportsPage.test.tsx
pnpm test:e2e -- e2e/dashboard/report-generate.spec.ts

3.7 /dashboard/leads — Lead Inbox#

Unit Tests#

Test Input Expected Output File
lead-list 20 leads Inbox-style list with Name, Phone, Source, Status, Date, Actions src/__tests__/unit/pages/LeadsPage.test.tsx
status-badge NEW / CONTACTED / CONVERTED / LOST Each status renders correct color via StatusBadge src/__tests__/unit/pages/LeadsPage.test.tsx
click-to-call Click phone number tel: link opens with correct number src/__tests__/unit/pages/LeadsPage.test.tsx
mark-contacted Click "Mark Contacted" Calls lead.updateStatus with CONTACTED; badge updates src/__tests__/unit/pages/LeadsPage.test.tsx
convert-lead Click "Convert" Status changes to CONVERTED; success toast src/__tests__/unit/pages/LeadsPage.test.tsx
archive-lead Click "Archive" Status changes to LOST; row fades or moves to archive tab src/__tests__/unit/pages/LeadsPage.test.tsx
lead-detail Click lead row Detail panel slides in with full message, source URL, UTM params src/__tests__/unit/pages/LeadsPage.test.tsx
filter-by-source Select "Site" Only leads with source = SITE visible src/__tests__/unit/pages/LeadsPage.test.tsx
filter-by-status Select "NEW" Only NEW leads visible src/__tests__/unit/pages/LeadsPage.test.tsx
search-leads Type "Raj" Only leads with "Raj" in name/phone/message visible src/__tests__/unit/pages/LeadsPage.test.tsx
empty-inbox 0 leads EmptyState with "No leads yet" message src/__tests__/unit/pages/LeadsPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
lead-management-flow 1. Go to /dashboard/leads. 2. Click first lead. 3. Mark contacted. 4. Convert. 5. Archive another. Lead status changes reflected in list and filters. e2e/dashboard/lead-management.spec.ts

Success Criteria (Binary)#

  • SC-LEADS-01: Lead list renders all columns with correct data alignment.
  • SC-LEADS-02: Status badges use correct colors (NEW=blue, CONTACTED=yellow, CONVERTED=green, LOST=gray).
  • SC-LEADS-03: Phone numbers are clickable tel: links.
  • SC-LEADS-04: Mark Contacted, Convert, and Archive buttons call lead.updateStatus.
  • SC-LEADS-05: Lead detail panel shows full message, source URL, and UTM parameters.
  • SC-LEADS-06: Filters by source (Site, GBP, Social, Direct) work correctly.
  • SC-LEADS-07: Filters by status work correctly.
  • SC-LEADS-08: Search filters by name, phone, and message content.
  • SC-LEADS-09: Empty state shows when no leads match filters.
  • SC-LEADS-10: Archived leads can be viewed via "Archive" tab or toggle.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Lead records (20), mix of statuses and sources.
  • Required env vars: None.
  • Required external mocks: None.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/LeadsPage.test.tsx
pnpm test:e2e -- e2e/dashboard/lead-management.spec.ts

3.8 /dashboard/content — Content Approval#

Unit Tests#

Test Input Expected Output File
content-cards 5 pending items Card list with type, preview, timer, action buttons src/__tests__/unit/pages/ContentApprovalPage.test.tsx
auto-publish-timer Content queued 2 hours ago Countdown shows "22 hours remaining" src/__tests__/unit/pages/ContentApprovalPage.test.tsx
approve-gbp-post Click "Approve" on GBP Post card Calls content.approve; card removed; toast success src/__tests__/unit/pages/ContentApprovalPage.test.tsx
reject-social-post Click "Reject" on Social Post card Calls content.reject; card removed; toast info src/__tests__/unit/pages/ContentApprovalPage.test.tsx
edit-content Click "Edit" on content card Inline editor opens; save calls content.update; timer resets src/__tests__/unit/pages/ContentApprovalPage.test.tsx
content-type-badges GBP Post, Social Post, Review Reply, Directory Profile Content, FAQ Each type renders correct icon + label src/__tests__/unit/pages/ContentApprovalPage.test.tsx
empty-queue 0 pending items EmptyState with "All caught up!" message src/__tests__/unit/pages/ContentApprovalPage.test.tsx
negative-review-reply Review reply for 1-star review Card shows review context + suggested reply; Approve required src/__tests__/unit/pages/ContentApprovalPage.test.tsx
faq-optional FAQ content Badge shows "Optional"; Approve/Reject still available src/__tests__/unit/pages/ContentApprovalPage.test.tsx
timer-expiry Timer reaches 0 Auto-calls content.approve; content published src/__tests__/unit/pages/ContentApprovalPage.test.tsx

Interaction Tests#

Test Action Expected Result File
card-expand Click content preview Card expands to show full content src/__tests__/unit/pages/ContentApprovalPage.test.tsx
swipe-approve Swipe right on mobile Calls content.approve with haptic feedback e2e/dashboard/content-approval-mobile.spec.ts
swipe-reject Swipe left on mobile Calls content.reject with haptic feedback e2e/dashboard/content-approval-mobile.spec.ts
bulk-approve Select 3 cards; click "Approve All" Calls content.approve for all 3; bulk toast src/__tests__/unit/pages/ContentApprovalPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
content-approval-workflow 1. AI generates GBP Post. 2. Navigate to /dashboard/content. 3. Click Edit. 4. Modify text. 5. Approve. 6. Verify published. Content appears on live GBP. e2e/dashboard/content-approval.spec.ts

Success Criteria (Binary)#

  • SC-CONTENT-01: Content queue shows all pending items with type badge, preview, and countdown timer.
  • SC-CONTENT-02: Countdown timer accurately reflects 24h auto-publish window.
  • SC-CONTENT-03: Approve button calls content.approve and removes card from queue.
  • SC-CONTENT-04: Reject button calls content.reject and archives content.
  • SC-CONTENT-05: Edit button opens inline editor; save resets timer and updates content.
  • SC-CONTENT-06: Content type badges match spec (GBP Post, Social Post, Review Reply, Directory Profile Content, FAQ).
  • SC-CONTENT-07: Negative review replies require approval; positive review replies auto-approve.
  • SC-CONTENT-08: FAQ content marked as "Optional" but still supports Approve/Reject.
  • SC-CONTENT-09: Timer expiry auto-approves and publishes content.
  • SC-CONTENT-10: Empty queue shows celebratory empty state.
  • SC-CONTENT-11: Mobile swipe gestures work for Approve (right) and Reject (left).
  • SC-CONTENT-12: Bulk approve selects multiple cards and processes in batch.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Content records (5 pending: 2 GBP Posts, 1 Social Post, 1 Review Reply, 1 FAQ), mix of PENDING_REVIEW status.
  • Required env vars: AI_SERVICE_URL.
  • Required external mocks: msw for AI content generation, GBP publish API, Social publish API.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/ContentApprovalPage.test.tsx
pnpm test:e2e -- e2e/dashboard/content-approval.spec.ts
pnpm test:e2e -- e2e/dashboard/content-approval-mobile.spec.ts

3.9 /dashboard/settings — Practice Settings#

Unit Tests#

Test Input Expected Output File
business-info-tab Practice data Name, type, logo, colors editable; save calls practice.update src/__tests__/unit/pages/SettingsPage.test.tsx
locations-tab 2 locations Location cards render with address, phone, hours; add/edit/delete work src/__tests__/unit/pages/SettingsPage.test.tsx
add-location Click "Add Location" Modal opens; form validates; submit calls location.create src/__tests__/unit/pages/SettingsPage.test.tsx
edit-location Click "Edit" on location card Modal opens pre-filled; save calls location.update src/__tests__/unit/pages/SettingsPage.test.tsx
delete-location Click "Delete" on location card ConfirmDialog opens; confirm calls location.delete src/__tests__/unit/pages/SettingsPage.test.tsx
team-members-tab 3 members Member list with name, email, role; invite/remove/change role src/__tests__/unit/pages/SettingsPage.test.tsx
invite-member Input email, select role Calls team.invite; email sent; member appears as "Pending" src/__tests__/unit/pages/SettingsPage.test.tsx
remove-member Click "Remove" on member ConfirmDialog; confirm removes from list src/__tests__/unit/pages/SettingsPage.test.tsx
change-role Select new role from dropdown Calls team.updateRole; badge updates src/__tests__/unit/pages/SettingsPage.test.tsx
notifications-tab Email preferences Toggle switches for report emails, lead alerts, review alerts src/__tests__/unit/pages/SettingsPage.test.tsx
integrations-tab Connected services GBP reconnect button, social reconnect buttons visible src/__tests__/unit/pages/SettingsPage.test.tsx
tab-navigation Click each tab Content switches; URL updates with ?tab=... src/__tests__/unit/pages/SettingsPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
settings-team-management 1. Go to /dashboard/settings. 2. Invite new EDITOR. 3. Change role to VIEWER. 4. Remove member. Team list reflects changes; invited email sent. e2e/dashboard/settings-team.spec.ts

Success Criteria (Binary)#

  • SC-SETTINGS-01: Business Info tab edits name, type, logo, and brand colors; saves via practice.update.
  • SC-SETTINGS-02: Locations tab lists all locations with add/edit/delete functionality.
  • SC-SETTINGS-03: Add Location modal validates required fields (name, address, phone).
  • SC-SETTINGS-04: Delete Location requires confirmation and warns if only 1 location remains.
  • SC-SETTINGS-05: Team Members tab lists all members with roles.
  • SC-SETTINGS-06: Invite member sends email and shows pending status until accepted.
  • SC-SETTINGS-07: Remove member requires confirmation and prevents removing owner (CLIENT).
  • SC-SETTINGS-08: Change role updates immediately and reflects in permission matrix.
  • SC-SETTINGS-09: Notifications tab toggles email preferences and persists.
  • SC-SETTINGS-10: Integrations tab shows reconnect buttons for disconnected services.
  • SC-SETTINGS-11: Tab navigation updates URL query parameter and persists on refresh.
  • SC-SETTINGS-12: Logo upload validates image type and max size (2MB).

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Location (2), TeamMember (3: 1 CLIENT, 1 EDITOR, 1 VIEWER).
  • Required env vars: RESEND_API_KEY.
  • Required external mocks: msw for Resend email API, Google OAuth reconnect.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/SettingsPage.test.tsx
pnpm test:e2e -- e2e/dashboard/settings-team.spec.ts

3.10 /dashboard/billing — Billing#

Unit Tests#

Test Input Expected Output File
current-plan-card Premium plan, Rs 12,000/mo, next billing Feb 15 Card shows plan name, price, next billing date, feature list src/__tests__/unit/pages/BillingPage.test.tsx
feature-list Premium plan features 5 checkmarks: 30 Citations, 12 Social Posts, Custom Domain, 12 GBP Posts, Priority Support src/__tests__/unit/pages/BillingPage.test.tsx
upgrade-button Click "Upgrade" Opens plan comparison modal with 4 plans src/__tests__/unit/pages/BillingPage.test.tsx
cancel-button Click "Cancel" ConfirmDialog opens; confirm calls billing.cancel src/__tests__/unit/pages/BillingPage.test.tsx
plan-comparison 4 plans Table with Starter, Standard, Premium, Enterprise columns src/__tests__/unit/pages/BillingPage.test.tsx
select-plan Click "Select" on Enterprise Calls billing.createSubscription with new plan; success toast src/__tests__/unit/pages/BillingPage.test.tsx
invoice-table 6 invoices Table with date, amount, status, download link src/__tests__/unit/pages/BillingPage.test.tsx
download-invoice Click "Download" on invoice Triggers PDF download with invoice number src/__tests__/unit/pages/BillingPage.test.tsx
payment-method Saved card Card ending in ****4242 visible; update button opens Stripe/Razorpay modal src/__tests__/unit/pages/BillingPage.test.tsx
billing-history 12 months Pagination or scroll loads older invoices src/__tests__/unit/pages/BillingPage.test.tsx

E2E Tests#

Flow Steps Expected End State File
billing-upgrade-flow 1. Go to /dashboard/billing. 2. Click "Upgrade". 3. Select Premium. 4. Enter test card. 5. Confirm. Plan updated to Premium; invoice generated. e2e/dashboard/billing-upgrade.spec.ts

Success Criteria (Binary)#

  • SC-BILLING-01: Current plan card displays plan name, monthly price, next billing date, and all included features.
  • SC-BILLING-02: Feature list uses checkmarks for included features and crosses for excluded.
  • SC-BILLING-03: Upgrade button opens plan comparison modal.
  • SC-BILLING-04: Plan comparison table shows all 4 plans with correct pricing and limits.
  • SC-BILLING-05: Selecting a plan calls billing.createSubscription and shows success/error toast.
  • SC-BILLING-06: Cancel subscription requires confirmation and shows retention offer modal.
  • SC-BILLING-07: Invoice table lists all invoices with date, amount, status, and download link.
  • SC-BILLING-08: Download invoice triggers PDF download with correct filename.
  • SC-BILLING-09: Payment method shows last 4 digits and brand icon; update opens secure checkout.
  • SC-BILLING-10: Billing history supports pagination (10 invoices per page).
  • SC-BILLING-11: Failed payment shows error banner with "Update Payment Method" CTA.
  • SC-BILLING-12: Trial badge shows days remaining if plan is in trial period.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Subscription (Premium, active), Invoice (6 records), PaymentMethod (1 card).
  • Required env vars: STRIPE_SECRET_KEY or RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET.
  • Required external mocks: msw for Stripe/Razorpay API, checkout session.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/pages/BillingPage.test.tsx
pnpm test:e2e -- e2e/dashboard/billing-upgrade.spec.ts

4. Shared Component Tests#

4.1 Reusable Dashboard Components#

Component Unit Tests File
StatCard Renders value, label, trend arrow, color; handles loading and empty states src/__tests__/unit/components/StatCard.test.tsx
StatusBadge Renders correct color for each status enum; supports dot + icon variants src/__tests__/unit/components/StatusBadge.test.tsx
DataTable Renders columns, rows, sorting, pagination, empty state; keyboard navigation src/__tests__/unit/components/DataTable.test.tsx
EmptyState Renders icon, title, description, CTA button; handles no-CTA variant src/__tests__/unit/components/EmptyState.test.tsx
LoadingSkeleton Renders correct skeleton shape for card, table, list variants src/__tests__/unit/components/LoadingSkeleton.test.tsx
ConfirmDialog Renders title, description, confirm/cancel buttons; calls onConfirm/onCancel src/__tests__/unit/components/ConfirmDialog.test.tsx
DatePicker Opens calendar; selects date; blocks past dates; respects timezone src/__tests__/unit/components/DatePicker.test.tsx
ImageUploader Handles drag-drop; validates type/size; shows preview; calls onUpload src/__tests__/unit/components/ImageUploader.test.tsx
RichTextEditor Renders toolbar; bold/italic/link; outputs HTML; sanitizes input src/__tests__/unit/components/RichTextEditor.test.tsx
AIAssistButton Shows sparkle icon; click calls onGenerate; loading state; error state src/__tests__/unit/components/AIAssistButton.test.tsx

Success Criteria (Binary)#

  • SC-SHARED-01: StatCard renders all props correctly and shows skeleton when isLoading.
  • SC-SHARED-02: StatusBadge maps every status enum to correct semantic color.
  • SC-SHARED-03: DataTable supports column sorting, pagination, and row selection.
  • SC-SHARED-04: EmptyState renders icon, title, description, and optional CTA.
  • SC-SHARED-05: LoadingSkeleton has variants for card, table, list, and chart.
  • SC-SHARED-06: ConfirmDialog requires explicit confirm; cancel closes without action.
  • SC-SHARED-07: DatePicker blocks past dates and formats ISO string correctly.
  • SC-SHARED-08: ImageUploader validates file type (jpg, png, webp, gif) and max size.
  • SC-SHARED-09: RichTextEditor outputs sanitized HTML; toolbar buttons work.
  • SC-SHARED-10: AIAssistButton shows loading spinner during generation and error tooltip on failure.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/components/StatCard.test.tsx
pnpm test:unit -- src/__tests__/unit/components/StatusBadge.test.tsx
pnpm test:unit -- src/__tests__/unit/components/DataTable.test.tsx
pnpm test:unit -- src/__tests__/unit/components/EmptyState.test.tsx
pnpm test:unit -- src/__tests__/unit/components/LoadingSkeleton.test.tsx
pnpm test:unit -- src/__tests__/unit/components/ConfirmDialog.test.tsx
pnpm test:unit -- src/__tests__/unit/components/DatePicker.test.tsx
pnpm test:unit -- src/__tests__/unit/components/ImageUploader.test.tsx
pnpm test:unit -- src/__tests__/unit/components/RichTextEditor.test.tsx
pnpm test:unit -- src/__tests__/unit/components/AIAssistButton.test.tsx

5. Role-Based Access Matrix Tests#

5.1 Permission Enforcement#

For every route and mutation, verify UI enforcement and API enforcement across all three roles.

Unit Tests — UI Enforcement#

Test Role Page Action Expected UI File
client-full-access CLIENT All pages View + Edit All buttons, forms, menus visible and enabled src/__tests__/unit/access/RoleAccess.test.tsx
editor-content-access EDITOR /dashboard/gbp/posts Create Post "Create Post" button visible and clickable src/__tests__/unit/access/RoleAccess.test.tsx
editor-settings-readonly EDITOR /dashboard/settings Edit Business Info Form inputs disabled; save button hidden src/__tests__/unit/access/RoleAccess.test.tsx
editor-billing-hidden EDITOR /dashboard View Billing "Billing" nav item hidden src/__tests__/unit/access/RoleAccess.test.tsx
editor-team-hidden EDITOR /dashboard/settings Manage Team "Team Members" tab hidden or disabled src/__tests__/unit/access/RoleAccess.test.tsx
viewer-readonly VIEWER /dashboard/gbp/posts Create Post "Create Post" button hidden src/__tests__/unit/access/RoleAccess.test.tsx
viewer-readonly-reviews VIEWER /dashboard/gbp/reviews Reply "Reply" button hidden src/__tests__/unit/access/RoleAccess.test.tsx
viewer-readonly-site VIEWER /dashboard/profile Edit Hero Editor panel hidden or all inputs disabled src/__tests__/unit/access/RoleAccess.test.tsx
viewer-readonly-leads VIEWER /dashboard/leads Mark Contacted Action buttons hidden src/__tests__/unit/access/RoleAccess.test.tsx
viewer-content-readonly VIEWER /dashboard/content Approve Approve/Reject/Edit buttons hidden src/__tests__/unit/access/RoleAccess.test.tsx

Integration Tests — API Enforcement#

Test Role Mutation Expected Response File
api-editor-cannot-edit-settings EDITOR practice.update HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-editor-cannot-view-billing EDITOR billing.getPlan HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-viewer-cannot-create-post VIEWER gbp.createPost HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-viewer-cannot-reply-review VIEWER gbp.replyToReview HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-viewer-cannot-update-lead VIEWER lead.updateStatus HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-viewer-cannot-approve-content VIEWER content.approve HTTP 403 src/__tests__/integration/access/ApiAccess.test.ts
api-client-can-all CLIENT Any mutation HTTP 200 (valid input) src/__tests__/integration/access/ApiAccess.test.ts

E2E Tests#

Flow Role Steps Expected End State File
viewer-readonly-flow VIEWER 1. Login. 2. Visit all pages. 3. Attempt to click hidden buttons. No mutations triggered; no 403 errors from UI (buttons absent). e2e/access/viewer-readonly.spec.ts
editor-limited-flow EDITOR 1. Login. 2. Create GBP post. 3. Attempt to edit settings. 4. Attempt to view billing. Post created successfully; settings form disabled; billing nav absent. e2e/access/editor-limited.spec.ts

Success Criteria (Binary)#

  • SC-ACCESS-01: CLIENT role sees all nav items, buttons, and forms across all pages.
  • SC-ACCESS-02: EDITOR role can create/edit content (posts, replies, social, site) but cannot edit settings, manage team, or view billing.
  • SC-ACCESS-03: EDITOR role sees read-only settings and team tabs (or tabs are hidden).
  • SC-ACCESS-04: VIEWER role sees all pages but all edit/create/approve buttons are hidden.
  • SC-ACCESS-05: VIEWER role forms are disabled; no mutation buttons visible.
  • SC-ACCESS-06: API returns 403 for unauthorized mutations regardless of UI state.
  • SC-ACCESS-07: Navigation respects role: hidden nav items do not appear in sidebar.
  • SC-ACCESS-08: Role change in settings immediately updates UI permissions without reload.

Agent Context (Pre-conditions)#

  • Required DB state: User (3 records: 1 CLIENT, 1 EDITOR, 1 VIEWER), all linked to same Practice.
  • Required env vars: NEXTAUTH_SECRET.
  • Required external mocks: None.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/access/RoleAccess.test.tsx
pnpm test:integration -- src/__tests__/integration/access/ApiAccess.test.ts
pnpm test:e2e -- e2e/access/viewer-readonly.spec.ts
pnpm test:e2e -- e2e/access/editor-limited.spec.ts

6. Responsive Behavior Tests#

6.1 Breakpoint Compliance#

Breakpoint Width Sidebar Content Pages
Desktop >1024px Fixed 240px Full grid All
Tablet 768-1024px Collapsible 64px Adjusted grids All
Mobile <768px Hidden, hamburger Stacked cards All

Unit Tests — Responsive Hooks/Components#

Test Viewport Component Expected Behavior File
use-media-query-desktop 1280px DashboardShell Sidebar fixed at 240px; content full width src/__tests__/unit/responsive/Responsive.test.tsx
use-media-query-tablet 900px DashboardShell Sidebar collapsed to 64px; toggle visible src/__tests__/unit/responsive/Responsive.test.tsx
use-media-query-mobile 375px DashboardShell Sidebar hidden; hamburger menu visible src/__tests__/unit/responsive/Responsive.test.tsx
data-table-to-cards 375px DataTable Renders as card list instead of table src/__tests__/unit/responsive/Responsive.test.tsx
chart-simplified 375px GbpInsightsPage Charts show fewer data points or simplified axes src/__tests__/unit/responsive/Responsive.test.tsx
site-preview-modal 375px SitePreviewPage Preview opens in full-screen modal; editor below src/__tests__/unit/responsive/Responsive.test.tsx
content-swipe 375px ContentApprovalPage Cards support swipe gestures (Approve right, Reject left) src/__tests__/unit/responsive/Responsive.test.tsx
bottom-nav 375px DashboardSidebar Renders as bottom nav bar with 5 icons src/__tests__/unit/responsive/Responsive.test.tsx
stat-cards-stack 375px DashboardHomePage 6 stat cards stack in 1-column layout src/__tests__/unit/responsive/Responsive.test.tsx
report-cards-stack 375px ReportsPage Report cards stack in 1-column layout src/__tests__/unit/responsive/Responsive.test.tsx

E2E Tests — Responsive Flows#

Flow Viewport Steps Expected End State File
mobile-navigation 375px 1. Open hamburger. 2. Tap "GBP". 3. Tap sub-route "Posts". Navigates to /dashboard/gbp/posts; sidebar closes. e2e/responsive/mobile-navigation.spec.ts
tablet-collapse 900px 1. Click collapse sidebar. 2. Navigate to Reports. 3. Expand sidebar. Content adjusts width; nav labels hidden when collapsed. e2e/responsive/tablet-collapse.spec.ts
mobile-content-approval 375px 1. Go to /dashboard/content. 2. Swipe right on card. 3. Swipe left on card. Approve and Reject actions triggered with toast feedback. e2e/responsive/mobile-content-approval.spec.ts
mobile-lead-inbox 375px 1. Go to /dashboard/leads. 2. Tap lead. 3. Tap "Mark Contacted". Detail panel opens as bottom sheet; status updates. e2e/responsive/mobile-lead-inbox.spec.ts

Success Criteria (Binary)#

  • SC-RESPONSIVE-01: Desktop (>1024px): sidebar fixed at 240px; all grids use multi-column layout.
  • SC-RESPONSIVE-02: Tablet (768-1024px): sidebar collapsible to 64px; grids adjust to 2 columns.
  • SC-RESPONSIVE-03: Mobile (<768px): sidebar hidden; hamburger opens drawer; bottom nav option available.
  • SC-RESPONSIVE-04: Data tables render as card lists on mobile.
  • SC-RESPONSIVE-05: Charts simplify or reduce data points on mobile.
  • SC-RESPONSIVE-06: Site preview opens in modal or full-screen on mobile.
  • SC-RESPONSIVE-07: Content approval supports swipe gestures on mobile.
  • SC-RESPONSIVE-08: Lead detail opens as bottom sheet on mobile.
  • SC-RESPONSIVE-09: Stat cards stack to 1 column on mobile.
  • SC-RESPONSIVE-10: No horizontal scroll on any page at any breakpoint.
  • SC-RESPONSIVE-11: Touch targets are ≥44px on mobile.
  • SC-RESPONSIVE-12: Font sizes remain readable (≥14px) on all breakpoints.

Agent Context (Pre-conditions)#

  • Required DB state: Standard practice data across all pages.
  • Required env vars: None.
  • Required external mocks: None.
  • Required tooling: Playwright viewport emulation (Desktop 1280x720, Tablet 900x600, Mobile 375x812).

Verification Commands#

pnpm test:unit -- src/__tests__/unit/responsive/Responsive.test.tsx
pnpm test:e2e -- e2e/responsive/mobile-navigation.spec.ts
pnpm test:e2e -- e2e/responsive/tablet-collapse.spec.ts
pnpm test:e2e -- e2e/responsive/mobile-content-approval.spec.ts
pnpm test:e2e -- e2e/responsive/mobile-lead-inbox.spec.ts

7. Content Approval Workflow Tests#

7.1 State Machine Tests#

State Trigger Next State Test File
DRAFT Auto-queue (24h) PENDING_REVIEW Timer starts; card appears in queue src/__tests__/unit/workflow/ContentWorkflow.test.ts
PENDING_REVIEW Approve APPROVED → Auto-publish content.approve called; status updates; published src/__tests__/unit/workflow/ContentWorkflow.test.ts
PENDING_REVIEW Reject REJECTED content.reject called; card removed; archived src/__tests__/unit/workflow/ContentWorkflow.test.ts
PENDING_REVIEW Edit + Save PENDING_REVIEW (timer reset) content.update called; timer resets to 24h src/__tests__/unit/workflow/ContentWorkflow.test.ts
PENDING_REVIEW Timer expires APPROVED → Auto-publish Timer hits 0; auto-approve; auto-publish src/__tests__/unit/workflow/ContentWorkflow.test.ts
APPROVED PUBLISHED Webhook confirms publish; status updates src/__tests__/unit/workflow/ContentWorkflow.test.ts
REJECTED Regenerate DRAFT AI regenerates; new card appears in queue src/__tests__/unit/workflow/ContentWorkflow.test.ts

E2E Tests#

Flow Steps Expected End State File
full-approval-lifecycle 1. AI generates GBP Post (DRAFT). 2. Wait for PENDING_REVIEW. 3. Edit content. 4. Approve. 5. Verify published. Content live on GBP; status = PUBLISHED. e2e/workflow/content-approval-lifecycle.spec.ts
auto-publish-timer 1. AI generates content. 2. Do not interact. 3. Wait 24h (mocked). Content auto-publishes; status = PUBLISHED. e2e/workflow/content-auto-publish.spec.ts
reject-and-regenerate 1. AI generates content. 2. Reject. 3. Click "Regenerate". 4. New content appears. New content in queue with fresh timer. e2e/workflow/content-reject-regenerate.spec.ts

Success Criteria (Binary)#

  • SC-WORKFLOW-01: DRAFT content auto-queues to PENDING_REVIEW within 5 minutes of generation.
  • SC-WORKFLOW-02: PENDING_REVIEW content shows 24h countdown timer.
  • SC-WORKFLOW-03: Approve transitions to APPROVED and triggers immediate publish.
  • SC-WORKFLOW-04: Reject transitions to REJECTED and archives content.
  • SC-WORKFLOW-05: Edit resets timer to 24h and keeps status as PENDING_REVIEW.
  • SC-WORKFLOW-06: Timer expiry auto-approves and auto-publishes content.
  • SC-WORKFLOW-07: APPROVED content transitions to PUBLISHED upon webhook confirmation.
  • SC-WORKFLOW-08: Rejected content supports "Regenerate" which creates new DRAFT.
  • SC-WORKFLOW-09: Medical compliance scan runs before every state transition to PUBLISHED.
  • SC-WORKFLOW-10: Audit log records every state transition with user ID, timestamp, and action.

Agent Context (Pre-conditions)#

  • Required DB state: Practice with Content records in each state (DRAFT, PENDING_REVIEW, APPROVED, PUBLISHED, REJECTED).
  • Required env vars: AI_SERVICE_URL, BULLMQ_REDIS_URL.
  • Required external mocks: msw for AI generation, GBP publish API, social publish API, webhook delivery.
  • Required job queue: BullMQ worker running for content.autoPublish job.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/workflow/ContentWorkflow.test.ts
pnpm test:e2e -- e2e/workflow/content-approval-lifecycle.spec.ts
pnpm test:e2e -- e2e/workflow/content-auto-publish.spec.ts
pnpm test:e2e -- e2e/workflow/content-reject-regenerate.spec.ts

8. Visual Regression Test Points#

8.1 Screenshot Coverage#

Capture baseline screenshots for the following states and pages. All tests run at Desktop (1280x720) and Mobile (375x812).

Page State Screenshot Name File
/dashboard Loaded with data home-overview-loaded e2e/visual/dashboard-home.spec.ts
/dashboard Loading home-overview-loading e2e/visual/dashboard-home.spec.ts
/dashboard Empty home-overview-empty e2e/visual/dashboard-home.spec.ts
/dashboard/gbp Overview connected gbp-overview-connected e2e/visual/gbp-overview.spec.ts
/dashboard/gbp Overview disconnected gbp-overview-disconnected e2e/visual/gbp-overview.spec.ts
/dashboard/gbp/posts Calendar view gbp-posts-calendar e2e/visual/gbp-posts.spec.ts
/dashboard/gbp/posts Create modal open gbp-posts-create-modal e2e/visual/gbp-posts.spec.ts
/dashboard/gbp/reviews Filtered unreplied gbp-reviews-filtered e2e/visual/gbp-reviews.spec.ts
/dashboard/gbp/insights Charts loaded gbp-insights-charts e2e/visual/gbp-insights.spec.ts
/dashboard/social Accounts connected social-accounts e2e/visual/social-overview.spec.ts
/dashboard/social Compose open social-compose e2e/visual/social-overview.spec.ts
/dashboard/citations Table loaded citations-table e2e/visual/citations.spec.ts
/dashboard/citations Mismatch modal open citations-mismatch-modal e2e/visual/citations.spec.ts
/dashboard/profile Desktop preview site-preview-desktop e2e/visual/site-preview.spec.ts
/dashboard/profile Mobile preview site-preview-mobile e2e/visual/site-preview.spec.ts
/dashboard/reports Cards loaded reports-cards e2e/visual/reports.spec.ts
/dashboard/reports PDF viewer open reports-pdf-viewer e2e/visual/reports.spec.ts
/dashboard/leads Inbox loaded leads-inbox e2e/visual/leads.spec.ts
/dashboard/leads Detail panel open leads-detail-panel e2e/visual/leads.spec.ts
/dashboard/content Queue loaded content-queue e2e/visual/content-approval.spec.ts
/dashboard/content Edit inline open content-edit-inline e2e/visual/content-approval.spec.ts
/dashboard/settings Business info tab settings-business-info e2e/visual/settings.spec.ts
/dashboard/settings Team members tab settings-team-members e2e/visual/settings.spec.ts
/dashboard/billing Plan card billing-plan-card e2e/visual/billing.spec.ts
/dashboard/billing Plan comparison modal billing-plan-modal e2e/visual/billing.spec.ts
Sidebar Expanded sidebar-expanded e2e/visual/sidebar.spec.ts
Sidebar Collapsed sidebar-collapsed e2e/visual/sidebar.spec.ts
Sidebar Mobile drawer sidebar-mobile-drawer e2e/visual/sidebar.spec.ts
Error states 404 page error-404 e2e/visual/error-pages.spec.ts
Error states 500 page error-500 e2e/visual/error-pages.spec.ts

Success Criteria (Binary)#

  • SC-VISUAL-01: Baseline screenshots exist for all 31 states listed above.
  • SC-VISUAL-02: Argos diffs show ≤1% pixel variance for intentional changes.
  • SC-VISUAL-03: Mobile screenshots capture bottom nav or drawer layout correctly.
  • SC-VISUAL-04: Dark mode screenshots captured if theme toggle exists (optional).
  • SC-VISUAL-05: Loading states show skeletons, not empty whitespace.
  • SC-VISUAL-06: Modals and drawers are fully visible within viewport bounds.
  • SC-VISUAL-07: Charts and graphs render consistently (no random data shifts in baselines).

Agent Context (Pre-conditions)#

  • Required DB state: Full seeded dataset with consistent values (no random data).
  • Required env vars: ARGOS_TOKEN (if using Argos CI).
  • Required external mocks: All external APIs mocked to return deterministic responses.
  • Required tooling: Playwright + @argos-ci/playwright.

Verification Commands#

# Capture baselines
pnpm test:visual:baseline

# Run visual diff
pnpm test:visual

# Update baselines after intentional change
pnpm test:visual:update

9. Cross-Cutting Concerns#

9.1 Accessibility (a11y)#

Test Scope Criteria File
axe-dashboard-home /dashboard 0 violations (WCAG 2.1 AA) e2e/a11y/dashboard-home.spec.ts
axe-gbp-pages /dashboard/gbp/* 0 critical violations e2e/a11y/gbp-pages.spec.ts
axe-social /dashboard/social 0 critical violations e2e/a11y/social.spec.ts
axe-citations /dashboard/citations 0 critical violations e2e/a11y/citations.spec.ts
axe-site /dashboard/profile 0 critical violations e2e/a11y/site.spec.ts
axe-reports /dashboard/reports 0 critical violations e2e/a11y/reports.spec.ts
axe-leads /dashboard/leads 0 critical violations e2e/a11y/leads.spec.ts
axe-content /dashboard/content 0 critical violations e2e/a11y/content.spec.ts
axe-settings /dashboard/settings 0 critical violations e2e/a11y/settings.spec.ts
axe-billing /dashboard/billing 0 critical violations e2e/a11y/billing.spec.ts
keyboard-nav All pages Full navigation possible without mouse e2e/a11y/keyboard-nav.spec.ts
screen-reader All pages Landmarks, headings, labels announced correctly e2e/a11y/screen-reader.spec.ts

Success Criteria (Binary)#

  • SC-A11Y-01: All pages pass axe-core with 0 critical violations.
  • SC-A11Y-02: All interactive elements have focus indicators.
  • SC-A11Y-03: All images have alt text; decorative images have alt="".
  • SC-A11Y-04: Color contrast ratios ≥4.5:1 for normal text, ≥3:1 for large text.
  • SC-A11Y-05: Form inputs have associated labels.
  • SC-A11Y-06: Modal dialogs trap focus and restore focus on close.
  • SC-A11Y-07: Sidebar navigation uses aria-current for active page.
  • SC-A11Y-08: Status changes announced via live regions (toasts, loading states).

Verification Commands#

pnpm test:a11y -- e2e/a11y/

9.2 Performance#

Test Page Metric Threshold File
lcp-home /dashboard LCP < 2.5s e2e/perf/dashboard-home.spec.ts
inp-home /dashboard INP < 200ms e2e/perf/dashboard-home.spec.ts
cls-home /dashboard CLS < 0.1 e2e/perf/dashboard-home.spec.ts
lcp-gbp /dashboard/gbp LCP < 2.5s e2e/perf/gbp-pages.spec.ts
lcp-reports /dashboard/reports LCP < 2.5s e2e/perf/reports.spec.ts
js-bundle-size All pages Total JS < 500KB (gzipped) Build analysis
chart-render-time /dashboard/gbp/insights Chart paint < 500ms e2e/perf/gbp-insights.spec.ts
table-render-time /dashboard/citations 30 rows < 300ms e2e/perf/citations.spec.ts

Success Criteria (Binary)#

  • SC-PERF-01: LCP < 2.5s on all dashboard pages.
  • SC-PERF-02: INP < 200ms on all dashboard pages.
  • SC-PERF-03: CLS < 0.1 on all dashboard pages.
  • SC-PERF-04: Total JS bundle < 500KB gzipped.
  • SC-PERF-05: Charts render within 500ms of data arrival.
  • SC-PERF-06: Data tables with 30 rows render within 300ms.
  • SC-PERF-07: No layout thrashing during sidebar collapse/expand.
  • SC-PERF-08: Images lazy-loaded below the fold.

Verification Commands#

pnpm test:perf -- e2e/perf/
# OR
pnpm lighthouse --preset=desktop http://localhost:3000/dashboard

9.3 Error Handling & Edge Cases#

Test Scenario Expected Behavior File
trpc-error-toast Any tRPC query fails Toast shows error message; retry button visible src/__tests__/unit/error-handling/ErrorHandling.test.tsx
network-offline Browser goes offline Offline banner appears; queued actions saved src/__tests__/unit/error-handling/ErrorHandling.test.tsx
session-expired Token expires mid-action Redirect to /login with ?redirectTo= src/__tests__/unit/error-handling/ErrorHandling.test.tsx
rate-limited GBP API returns 429 Toast shows "Rate limited, retrying in Xs"; exponential backoff src/__tests__/unit/error-handling/ErrorHandling.test.tsx
invalid-file-upload Upload .exe to ImageUploader Rejection toast; file not sent to server src/__tests__/unit/error-handling/ErrorHandling.test.tsx
oversized-file Upload 15MB image Rejection toast; max size warning src/__tests__/unit/error-handling/ErrorHandling.test.tsx
form-validation Submit empty required field Inline error message; submit blocked src/__tests__/unit/error-handling/ErrorHandling.test.tsx
timeout AI generation > 30s Loading state shows progress; timeout toast after 30s src/__tests__/unit/error-handling/ErrorHandling.test.tsx
concurrent-edit Two users edit same profile section Conflict modal with "Reload" and "Overwrite" options src/__tests__/unit/error-handling/ErrorHandling.test.tsx
data-corruption API returns malformed JSON Graceful fallback; empty state with retry CTA src/__tests__/unit/error-handling/ErrorHandling.test.tsx

Success Criteria (Binary)#

  • SC-ERROR-01: All tRPC errors show user-friendly toast with retry option.
  • SC-ERROR-02: Offline state shows banner and queues non-critical actions.
  • SC-ERROR-03: Session expiry redirects to login with original path preserved.
  • SC-ERROR-04: Rate-limited APIs retry with exponential backoff (max 3 retries).
  • SC-ERROR-05: Invalid file uploads rejected client-side before network request.
  • SC-ERROR-06: Form validation prevents submission and shows inline errors.
  • SC-ERROR-07: AI generation timeout shows progress and graceful failure message.
  • SC-ERROR-08: Concurrent edit conflict detected and resolved with user choice.
  • SC-ERROR-09: Malformed API responses fall back to empty state, not crash.
  • SC-ERROR-10: 404 and 500 pages render with helpful navigation links.

Verification Commands#

pnpm test:unit -- src/__tests__/unit/error-handling/ErrorHandling.test.tsx

10. Verification Commands Summary#

Run All Dashboard UI Tests#

# 1. Unit tests (all dashboard pages + components + access + responsive + error handling)
pnpm test:unit -- src/__tests__/unit/pages/
pnpm test:unit -- src/__tests__/unit/components/
pnpm test:unit -- src/__tests__/unit/layout/
pnpm test:unit -- src/__tests__/unit/access/
pnpm test:unit -- src/__tests__/unit/responsive/
pnpm test:unit -- src/__tests__/unit/error-handling/

# 2. Integration tests (layout + API access)
pnpm test:integration -- src/__tests__/integration/layout/
pnpm test:integration -- src/__tests__/integration/access/

# 3. E2E tests (all dashboard flows)
pnpm test:e2e -- e2e/dashboard/
pnpm test:e2e -- e2e/access/
pnpm test:e2e -- e2e/responsive/
pnpm test:e2e -- e2e/workflow/

# 4. Visual regression
pnpm test:visual

# 5. Accessibility
pnpm test:a11y -- e2e/a11y/

# 6. Performance
pnpm test:perf -- e2e/perf/

# 7. Compliance (medical content)
pnpm test:compliance -- src/__tests__/compliance/

# 8. Full dashboard suite (CI)
pnpm test:dashboard

Quick Checklist for Agent Verification#

Before marking any dashboard page task as complete, run:

# Unit tests for the page
pnpm test:unit -- src/__tests__/unit/pages/[PageName].test.tsx

# Integration tests for related routers
pnpm test:integration -- src/__tests__/integration/routers/[router].test.ts

# E2E smoke test for the page
pnpm test:e2e -- e2e/dashboard/[page-smoke].spec.ts

# Visual regression for the page
pnpm test:visual -- e2e/visual/[page].spec.ts

Success Criteria Summary (All Binary)#

Category Criteria Count Passing Condition
Shell & Layout 4 All checkboxes checked
Sidebar 5 All checkboxes checked
Header 4 All checkboxes checked
Home Overview 8 All checkboxes checked
GBP 13 All checkboxes checked
Social 10 All checkboxes checked
Citations 10 All checkboxes checked
Site 12 All checkboxes checked
Reports 8 All checkboxes checked
Leads 10 All checkboxes checked
Content Approval 12 All checkboxes checked
Settings 12 All checkboxes checked
Billing 12 All checkboxes checked
Shared Components 10 All checkboxes checked
Role-Based Access 8 All checkboxes checked
Responsive 12 All checkboxes checked
Content Workflow 10 All checkboxes checked
Visual Regression 7 All checkboxes checked
Accessibility 8 All checkboxes checked
Performance 8 All checkboxes checked
Error Handling 10 All checkboxes checked
TOTAL 173 All 173 criteria must pass

End of Test Specification — RankFlow AI User Dashboard UI v1.0.0