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
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)#
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
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)#
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
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)#
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)#
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)#
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
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)#
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)#
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)#
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)#
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)#
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)#
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)#
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)#
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)#
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)#
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)#
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)#
Verification Commands#
pnpm test:a11y -- e2e/a11y/
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)#
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)#
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