Test Scenarios: Campaign-to-Book Merge
Purpose: Comprehensive UI-based scenario testing for the campaign-to-book merge implementation Tester: QA / Intern Last Updated: 2025-12-04
Quick Reference: Key URLs
| URL | What to Verify |
|---|---|
/books | Book list loads, can create new |
/books/new | Wizard works end-to-end |
/books/[id] | Dashboard shows book info, stories |
/books/[id]/stories | Story list for book |
/books/[id]/stories/new | Create story with prompts |
/books/[id]/stories/[sid]/edit | Edit story, auto-save works |
/books/[id]/record | Voice recording, book-scoped |
/books/[id]/conversations | AI chat, book context |
/books/[id]/share | Sharing UI, action-oriented |
/books/[id]/settings | Book configuration |
/api/cron/weekly-prompts | Weekly prompts cron endpoint |
/settings/notifications | User notification preferences |
Test Accounts Required
- User A (Primary): Creates books, shares, tests owner flows
- User B (Family): Receives shares, tests permission boundaries
- User C (Gift Recipient): Tests gift acceptance flow
Part 1: Book Creation Flows
Scenario 1.1: Create Personal Memoir (Self Path)
Goal: Complete book creation wizard for “writing my own story”
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Go to /books/new | Wizard loads with path selection | [ ] |
| 2 | Select “I’m writing my own story” | Proceeds to template selection (skips storyteller step) | [ ] |
| 3 | Browse templates, select “Life Story Memoir” | Template preview shows chapters | [ ] |
| 4 | Click “Use This Template” | Proceeds to book details | [ ] |
| 5 | Enter title: “My Journey” | Title field accepts input | [ ] |
| 6 | Verify Goals step loads with defaults | 10 stories pre-selected with auto-populated target date | [ ] |
| 7 | See weekly prompts info box | Amber box says “We’ll send weekly story prompts” | [ ] |
| 8 | Select different goal (e.g., 15 stories) | Target date auto-adjusts (~15 weeks out) | [ ] |
| 9 | Optionally change target date | Date picker accepts custom date | [ ] |
| 10 | Select “No goal” option | Target date field hides | [ ] |
| 11 | Select 10 stories again | Target date auto-populates again | [ ] |
| 12 | Review summary screen | All entered info displays correctly | [ ] |
| 13 | Click “Start Book” | Book created, redirects to dashboard | [ ] |
| 14 | Verify dashboard | Title shows, progress 0/10, chapters visible | [ ] |
Scenario 1.2: Create Book for Family Member
Goal: Complete wizard for “capturing someone else’s story”
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Go to /books/new | Wizard loads | [ ] |
| 2 | Select “I’m capturing someone else’s story” | Proceeds to storyteller info step | [ ] |
| 3 | Enter storyteller name: “Grandma Rose” | Field accepts input | [ ] |
| 4 | Select relationship: “Grandparent” | Dropdown works | [ ] |
| 5 | Enter optional email | Field validates email format | [ ] |
| 6 | Continue through template selection | Template picker loads | [ ] |
| 7 | Select “Family History” template | Preview shows chapters | [ ] |
| 8 | Complete remaining steps | All steps work | [ ] |
| 9 | Verify dashboard | Shows “About: Grandma Rose” | [ ] |
Scenario 1.3: Create Gift Book
Goal: Complete gift flow with recipient info
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Go to /books/new | Wizard loads | [ ] |
| 2 | Select “I’m giving this as a gift” | Proceeds to gift recipient step | [ ] |
| 3 | Enter recipient name: “Dad” | Field accepts input | [ ] |
| 4 | Enter recipient email | Field validates | [ ] |
| 5 | Enter gift message | Text area accepts long message | [ ] |
| 6 | Complete template and book details | All steps work | [ ] |
| 7 | Review shows gift info | Recipient name, message visible | [ ] |
| 8 | Complete creation | Book marked as gift (is_gift: true) | [ ] |
Scenario 1.4: Wizard Navigation and Validation
Goal: Test wizard edge cases
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Start wizard, click Back on step 1 | Should not error/crash | [ ] |
| 2 | Try to proceed without selecting path | Validation prevents advance | [ ] |
| 3 | Try to proceed without selecting template | Validation prevents advance | [ ] |
| 4 | Leave title blank, try to continue | Validation shows error | [ ] |
| 5 | Enter very long title (100+ chars) | Truncates or shows error | [ ] |
| 6 | Navigate forward then back | Previous selections preserved | [ ] |
| 7 | Refresh browser mid-wizard | Progress preserved OR clean restart | [ ] |
| 8 | Close browser, return | Draft wizard state handled | [ ] |
Part 2: Story Creation and Editing
Scenario 2.1: Create Story by Writing
Goal: Test text-based story creation
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | From book dashboard, click “Add Story” | Story creation page loads | [ ] |
| 2 | See two equal options: Record / Write | Neither dominates visually | [ ] |
| 3 | Click “Write” | Editor loads | [ ] |
| 4 | See template prompt suggestions | Prompts relevant to chapter | [ ] |
| 5 | Select a prompt OR skip | Works both ways | [ ] |
| 6 | Type story title | Title saves | [ ] |
| 7 | Type 2+ paragraphs of content | Content accepts formatting | [ ] |
| 8 | Apply bold, italic, heading | Formatting works | [ ] |
| 9 | See auto-save indicator | Shows “Saving…” then “Saved” | [ ] |
| 10 | Click Done/Save | Returns to book dashboard | [ ] |
| 11 | Verify story appears in list | New story shows with title | [ ] |
| 12 | Progress counter updated | Shows 1/10 (or appropriate) | [ ] |
Scenario 2.2: Create Story by Voice Recording
Goal: Test voice recording flow
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | From book dashboard, click “Record” | Recording page loads at /books/[id]/record | [ ] |
| 2 | See large microphone button | Button is prominent, easy to tap | [ ] |
| 3 | Click to start recording | Recording starts, timer visible | [ ] |
| 4 | Speak for 15-30 seconds | Recording captures audio | [ ] |
| 5 | Click stop | Recording stops | [ ] |
| 6 | See playback option | Can listen to recording | [ ] |
| 7 | Click “Create Story from Recording” | Transcription begins | [ ] |
| 8 | See transcription result | Text appears (or loading state) | [ ] |
| 9 | Edit transcription if needed | Can modify text | [ ] |
| 10 | Save with title | Story created in book | [ ] |
| 11 | Return to record page | Recording shows in history | [ ] |
Scenario 2.3: Edit Existing Story
Goal: Test story editing workflow
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open book dashboard | Stories list visible | [ ] |
| 2 | Click on existing story | Story view loads | [ ] |
| 3 | Click “Edit” | Editor loads with content | [ ] |
| 4 | Modify title | Title updates | [ ] |
| 5 | Add paragraph to content | Content expands | [ ] |
| 6 | Delete some text | Content shrinks | [ ] |
| 7 | See auto-save working | Indicator shows saves | [ ] |
| 8 | Add an image (if supported) | Image uploads and displays | [ ] |
| 9 | Click Done | Returns to story view | [ ] |
| 10 | Verify changes persisted | All edits visible | [ ] |
Scenario 2.4: Draft Recovery After Crash
Goal: Test single-session draft persistence
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open existing story in edit mode | Editor loads | [ ] |
| 2 | Make significant changes | Add new paragraph | [ ] |
| 3 | DO NOT click save | Leave changes unsaved | [ ] |
| 4 | Close browser tab abruptly | Tab closes | [ ] |
| 5 | Reopen app, navigate to same story edit | Edit page loads | [ ] |
| 6 | See draft recovery modal | ”We found unsaved work” message | [ ] |
| 7 | Click “Restore” | Unsaved changes reappear | [ ] |
| 8 | Save properly | Content saves | [ ] |
| 9 | Close and reopen | No recovery modal (draft cleared) | [ ] |
Alternative path:
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 7a | Click “Discard” instead | Original content loads | [ ] |
| 8a | Verify draft cleared | No recovery on next visit | [ ] |
Scenario 2.5: Placeholder Stories (Progressive Reveal)
Goal: Test placeholder/chapter experience
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create new book with 12-chapter template | Book created | [ ] |
| 2 | View book dashboard | See encouraging first prompt (not all 12) | [ ] |
| 3 | Click on first placeholder | Editor opens with prompt context | [ ] |
| 4 | Write and save first story | Returns to dashboard | [ ] |
| 5 | See celebration/success message | Positive feedback shown | [ ] |
| 6 | See next prompt suggestions | ”Want to write another?” with ideas | [ ] |
| 7 | Toggle “View all chapters” (if available) | All 12 placeholders visible | [ ] |
| 8 | Delete an unwanted placeholder | Placeholder removed | [ ] |
| 9 | Reorder placeholders (if supported) | Order changes | [ ] |
Part 3: Book-Scoped Features
Scenario 3.1: Recordings Stay Book-Scoped
Goal: Verify recordings don’t leak between books
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create Book A with 1 recording | Recording saved | [ ] |
| 2 | Create Book B | New book created | [ ] |
| 3 | Go to Book A’s record page | See Book A’s recording | [ ] |
| 4 | Go to Book B’s record page | NO recordings visible (empty) | [ ] |
| 5 | Record in Book B | New recording saved | [ ] |
| 6 | Go back to Book A | Still only shows Book A’s recording | [ ] |
Scenario 3.2: AI Conversations Book-Scoped
Goal: Verify AI uses correct book context
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create Book A with story titled “My Childhood” | Story saved | [ ] |
| 2 | Go to Book A conversations | Chat loads | [ ] |
| 3 | Ask “What stories have I written?” | AI mentions “My Childhood” | [ ] |
| 4 | Create Book B (no stories) | Book created | [ ] |
| 5 | Go to Book B conversations | Chat loads | [ ] |
| 6 | Ask same question | AI does NOT mention “My Childhood” | [ ] |
Scenario 3.3: Multiple Books Stay Independent
Goal: Verify book isolation
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create Book A: “Dad’s Stories” | Book created | [ ] |
| 2 | Add 2 stories to Book A | Stories saved | [ ] |
| 3 | Create Book B: “My Childhood” | Book created | [ ] |
| 4 | Add 1 story to Book B | Story saved | [ ] |
| 5 | Open Book A dashboard | Shows only 2 stories | [ ] |
| 6 | Open Book B dashboard | Shows only 1 story | [ ] |
| 7 | Delete story from Book B | Book A unaffected | [ ] |
Part 4: Sharing and Permissions
Scenario 4.1: Share Book as View-Only
Goal: Test “Share” button (Viewer role)
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User A, open book you own | Book loads | [ ] |
| 2 | Go to Share page | /books/[id]/share loads | [ ] |
| 3 | Click “Share” button | Generates shareable link | [ ] |
| 4 | Copy link | Link copied to clipboard | [ ] |
| 5 | As User B, open link in incognito | Prompted to login or view | [ ] |
| 6 | Log in as User B | Book visible | [ ] |
| 7 | Try to edit a story | Edit button disabled/hidden | [ ] |
| 8 | Try to add new story | Add button disabled/hidden | [ ] |
| 9 | Verify can view all content | Stories readable | [ ] |
Scenario 4.2: Invite Family to Help (Contributor)
Goal: Test “Invite to Help” flow
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User A, go to Share page | Page loads | [ ] |
| 2 | Click “Invite to Help” | Invitation form appears | [ ] |
| 3 | Enter User B’s email | Email accepted | [ ] |
| 4 | See permission question | ”Should they edit your stories or only add their own?” | [ ] |
| 5 | Select “Only add their own” | Contributor role selected | [ ] |
| 6 | Send invitation | Success message | [ ] |
| 7 | As User B, check email | Invitation received | [ ] |
| 8 | Accept invitation | Book appears in User B’s list | [ ] |
| 9 | As User B, open the book | Can view all stories | [ ] |
| 10 | Try to edit User A’s story | Cannot edit (blocked) | [ ] |
| 11 | Add new story | Story created successfully | [ ] |
| 12 | Edit own story | Works | [ ] |
Scenario 4.3: Invite Family to Help (Editor)
Goal: Test full edit permission
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User A, invite User B as Editor | Select “Edit your stories” option | [ ] |
| 2 | As User B, accept and open book | Book accessible | [ ] |
| 3 | Edit User A’s story | Edit allowed | [ ] |
| 4 | Save changes | Changes persist | [ ] |
| 5 | As User A, view the story | See User B’s edits | [ ] |
Scenario 4.4: Revoke Permissions
Goal: Test permission removal
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User A, go to Share page | See User B listed | [ ] |
| 2 | Remove User B’s access | Confirmation prompt | [ ] |
| 3 | Confirm removal | User B removed | [ ] |
| 4 | As User B, try to access book | Access denied | [ ] |
Part 5: Gift Flow
Scenario 5.1: Send Gift Book
Goal: Test gift sending flow
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create gift book for User C | Book created with is_gift: true | [ ] |
| 2 | Optionally add starter stories | Stories saved | [ ] |
| 3 | Go to gift send flow | Send options appear | [ ] |
| 4 | Send gift to User C’s email | Gift sent, status: “sent” | [ ] |
| 5 | Check User A’s book list | Book shows as “Gift sent” | [ ] |
Scenario 5.2: Receive and Accept Gift
Goal: Test gift acceptance and ownership transfer
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User C, check email | Gift notification received | [ ] |
| 2 | Click accept link | Redirected to app | [ ] |
| 3 | Create account (if new) | Account created | [ ] |
| 4 | See gift acceptance screen | Gift message displayed | [ ] |
| 5 | Accept gift | Book ownership transfers | [ ] |
| 6 | Verify User C is now owner | Full edit/delete access | [ ] |
| 7 | Verify User A is contributor | Can still add stories | [ ] |
Scenario 5.3: Decline Gift
Goal: Test gift decline flow
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | As User C, click decline | Confirmation prompt | [ ] |
| 2 | Confirm decline | Gift declined | [ ] |
| 3 | As User A, see notification | Gift status: “declined” | [ ] |
| 4 | User A retains ownership | Book still accessible | [ ] |
Part 6: Template and Settings
Scenario 6.1: Change Template Mid-Project
Goal: Test template switching
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create book with “Quick Memoir” template | Book created | [ ] |
| 2 | Add 3 stories | Stories saved | [ ] |
| 3 | Go to Book Settings | Settings page loads | [ ] |
| 4 | Click “Change Template” | Template picker opens | [ ] |
| 5 | See warning message | ”Your stories will be preserved” | [ ] |
| 6 | Select “Life Story Memoir” | Template changes | [ ] |
| 7 | See mapping suggestions | ”These stories might fit…” | [ ] |
| 8 | Confirm change | Template updated | [ ] |
| 9 | Verify stories preserved | All 3 stories still exist | [ ] |
| 10 | See new prompt suggestions | New template prompts available | [ ] |
Scenario 6.2: Update Book Settings
Goal: Test settings modification
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open book settings | Settings page loads | [ ] |
| 2 | Change book title | New title saved | [ ] |
| 3 | Change notification frequency | Setting updated | [ ] |
| 4 | Update storyteller info | Info saved | [ ] |
| 5 | Return to dashboard | New title displayed | [ ] |
| 6 | Verify notification setting | Persisted correctly | [ ] |
Scenario 6.3: Delete Book
Goal: Test book deletion
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Go to book settings | Page loads | [ ] |
| 2 | Click “Delete Book” | Warning modal appears | [ ] |
| 3 | Warning mentions stories count | ”This book has X stories” | [ ] |
| 4 | Confirm deletion | Book deleted | [ ] |
| 5 | Redirected to book list | Book no longer visible | [ ] |
| 6 | Shared users lose access | User B can’t access | [ ] |
Part 7: Story Duplication
Scenario 7.1: Duplicate Story to Another Book
Goal: Test story duplication feature
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open a story in Book A | Story view loads | [ ] |
| 2 | Click “Duplicate to another book” | Modal shows book list | [ ] |
| 3 | Select Book B | Book B highlighted | [ ] |
| 4 | Click Duplicate | Success message | [ ] |
| 5 | Open Book B | See duplicated story | [ ] |
| 6 | Verify title has “(Copy)” suffix | Title modified | [ ] |
| 7 | Edit duplicated story | Changes save | [ ] |
| 8 | Check original in Book A | Unchanged | [ ] |
Part 8: Navigation and Routing
Scenario 8.1: URL Routes Work Correctly
Goal: Test all book-related routes
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Navigate to /books | Book list loads | [ ] |
| 2 | Navigate to /books/new | Wizard loads | [ ] |
| 3 | Navigate to /books/[valid-id] | Book dashboard loads | [ ] |
| 4 | Navigate to /books/[invalid-id] | 404 or error page | [ ] |
| 5 | Navigate to /books/[id]/stories | Story list loads | [ ] |
| 6 | Navigate to /books/[id]/stories/new | Create story page loads | [ ] |
| 7 | Navigate to /books/[id]/record | Recording page loads | [ ] |
| 8 | Navigate to /books/[id]/conversations | Chat loads | [ ] |
| 9 | Navigate to /books/[id]/share | Share page loads | [ ] |
| 10 | Navigate to /books/[id]/settings | Settings load | [ ] |
Scenario 8.2: Breadcrumb Navigation
Goal: Test navigation hierarchy
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Navigate deep: /books/[id]/stories/[sid]/edit | Page loads | [ ] |
| 2 | Check breadcrumbs | Shows: Books > Book Title > Story Title | [ ] |
| 3 | Click “Book Title” crumb | Returns to book dashboard | [ ] |
| 4 | Click “Books” crumb | Returns to book list | [ ] |
Scenario 8.3: Back Navigation
Goal: Test browser back button
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Books list > Book > Story > Edit | Navigate through flow | [ ] |
| 2 | Click browser back | Returns to story view | [ ] |
| 3 | Click back again | Returns to book dashboard | [ ] |
| 4 | Click back again | Returns to books list | [ ] |
Part 9: Mobile Experience
Scenario 9.1: Mobile Book Creation
Goal: Test wizard on mobile viewport
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Set viewport to 375px (iPhone) | Responsive layout | [ ] |
| 2 | Start book creation wizard | Single-column layout | [ ] |
| 3 | Verify buttons are 48px+ | Tappable targets | [ ] |
| 4 | Complete all wizard steps | All steps usable | [ ] |
| 5 | Verify bottom navigation | Bottom tabs visible | [ ] |
Scenario 9.2: Mobile Story Editing
Goal: Test editor on mobile
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open story editor on mobile | Editor loads | [ ] |
| 2 | Verify toolbar at bottom | Accessible by thumb | [ ] |
| 3 | Type content | Keyboard doesn’t obscure input | [ ] |
| 4 | Apply formatting | Toolbar buttons work | [ ] |
| 5 | See auto-save indicator | Visible on mobile | [ ] |
Scenario 9.3: Mobile Voice Recording
Goal: Test recording on mobile
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open record page on mobile | Page loads | [ ] |
| 2 | Mic button large and centered | Easy to tap | [ ] |
| 3 | Start/stop recording | Works on mobile | [ ] |
| 4 | Playback works | Audio plays | [ ] |
Part 10: Error Handling
Scenario 10.1: Network Error During Save
Goal: Test graceful error handling
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open story editor | Editor loads | [ ] |
| 2 | Make changes | Content modified | [ ] |
| 3 | Disable network (dev tools) | Offline mode | [ ] |
| 4 | See auto-save attempt | Shows “Saved locally” indicator | [ ] |
| 5 | Re-enable network | Online mode | [ ] |
| 6 | See sync complete | Content syncs to server | [ ] |
Scenario 10.2: Recording Upload Failure
Goal: Test recording error recovery
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Record a story | Recording saved locally | [ ] |
| 2 | Disable network | Offline | [ ] |
| 3 | Try to upload | Error message shown | [ ] |
| 4 | Verify recording not lost | Can retry later | [ ] |
| 5 | Re-enable network, retry | Upload succeeds | [ ] |
Scenario 10.3: Validation Errors
Goal: Test form validation
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create book with empty title | Error: “Title required” | [ ] |
| 2 | Create book with invalid email | Error: “Invalid email” | [ ] |
| 3 | Error messages are clear | Not technical jargon | [ ] |
| 4 | Error messages use amber color | Not alarming red | [ ] |
Part 11: Accessibility Quick Checks
Scenario 11.1: Keyboard Navigation
Goal: Test keyboard accessibility
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Tab through wizard steps | Focus moves logically | [ ] |
| 2 | Focus indicators visible | 3px amber outline | [ ] |
| 3 | Enter/Space activates buttons | All buttons work | [ ] |
| 4 | Escape closes modals | Modal dismissed | [ ] |
Scenario 11.2: Screen Reader Basics
Goal: Test assistive technology
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Enable VoiceOver/NVDA | Screen reader active | [ ] |
| 2 | Navigate to book list | ”Books” heading announced | [ ] |
| 3 | Save a story | ”Saved” status announced | [ ] |
| 4 | Error occurs | Error message announced | [ ] |
Part 12: Data Integrity
Scenario 12.1: Chapter Ordering (Junction Table)
Goal: Test concurrent editing doesn’t cause data loss
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create book with 5 stories | Stories ordered 1-5 | [ ] |
| 2 | As User A, start reordering | Drag story 3 to position 1 | [ ] |
| 3 | Simultaneously as User B, reorder | Drag story 5 to position 2 | [ ] |
| 4 | Both save | Both changes persist | [ ] |
| 5 | Refresh page | No stories lost | [ ] |
| 6 | Verify final order makes sense | No duplicates, no gaps | [ ] |
Scenario 12.2: Story Count Accuracy
Goal: Verify counts stay accurate
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create book with goal: 10 | Progress shows 0/10 | [ ] |
| 2 | Add 1 story | Progress shows 1/10 | [ ] |
| 3 | Add 2 more stories | Progress shows 3/10 | [ ] |
| 4 | Delete 1 story | Progress shows 2/10 | [ ] |
| 5 | Duplicate story from another book | Progress shows 3/10 | [ ] |
Part 13: Weekly Story Prompts System
Scenario 13.1: Weekly Prompts Cron Job Execution
Goal: Test the weekly prompts cron endpoint (requires CRON_SECRET)
Prerequisites:
- Set
CRON_SECRETenvironment variable in Vercel/local environment - Have at least one user with
email_frequency = 'weekly'andemail_notifications = true - User must have at least one book
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Make POST request to /api/cron/weekly-prompts without auth | Returns 401 Unauthorized | [ ] |
| 2 | Make POST with wrong Bearer token | Returns 401 Unauthorized | [ ] |
| 3 | Make POST with correct Bearer {CRON_SECRET} | Returns 200 with results | [ ] |
| 4 | Check response body | Contains processed, succeeded, failed, skipped counts | [ ] |
| 5 | Check prompt_delivery_log table | New entry created for processed users | [ ] |
| 6 | Run cron again within 6 days | User skipped (recently received prompt) | [ ] |
Scenario 13.2: Prompt Selection Algorithm
Goal: Test intelligent prompt selection
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Create book with “Life Story Memoir” template | Book created with template_type | [ ] |
| 2 | Trigger prompt for this user | Gets template-specific prompt | [ ] |
| 3 | Check prompt_delivery_log | Prompt text logged | [ ] |
| 4 | Trigger again (after 6+ days) | Gets DIFFERENT prompt (not repeated) | [ ] |
| 5 | Create book with no template | Book created | [ ] |
| 6 | Trigger prompt for this user | Gets generic fallback prompt | [ ] |
Scenario 13.3: Email Delivery (Resend Integration)
Goal: Test weekly prompt email sends correctly
Prerequisites:
- Resend API key configured
- User has valid email address
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Trigger cron for eligible user | Email queued in email_send_queue | [ ] |
| 2 | Check Resend dashboard | Email appears in sent list | [ ] |
| 3 | Open email in inbox | Email received | [ ] |
| 4 | Verify email content | Contains user name, prompt text, book title | [ ] |
| 5 | Verify “Write your story” CTA | Links to /books/[id]/write?prompt=... | [ ] |
| 6 | Verify unsubscribe link | Links to /settings/notifications | [ ] |
| 7 | Click write link | Opens app at correct book with prompt pre-filled | [ ] |
Scenario 13.4: User Prompt Preferences
Goal: Test user can control prompt frequency
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Go to /settings/notifications | Settings page loads | [ ] |
| 2 | Find email frequency setting | Options: weekly, monthly, never | [ ] |
| 3 | Set to “weekly” | Setting saved | [ ] |
| 4 | Trigger cron | User receives prompt | [ ] |
| 5 | Set to “never” | Setting saved | [ ] |
| 6 | Trigger cron | User skipped (notifications disabled) | [ ] |
| 7 | Set to “monthly” | Setting saved | [ ] |
| 8 | Check next prompt timing | Respects monthly interval | [ ] |
Scenario 13.5: Prompt Delivery Log Verification
Goal: Verify prompt tracking works correctly
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Query prompt_delivery_log before test | Note current count | [ ] |
| 2 | Trigger prompt delivery for User A | Entry created | [ ] |
| 3 | Verify log entry fields | user_id, book_id, prompt_text, delivered_at populated | [ ] |
| 4 | Attempt duplicate delivery same day | Blocked by 6-day check | [ ] |
| 5 | Check for leaks | User A’s prompts don’t appear for User B | [ ] |
Scenario 13.6: Template-Based Prompts (Seed Data)
Goal: Verify seeded prompts work for each template
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Query book_chapter_prompts table | 60+ prompts seeded | [ ] |
| 2 | Filter by template “life-story-memoir” | ~15 prompts found | [ ] |
| 3 | Filter by template “quick-memoir” | ~15 prompts found | [ ] |
| 4 | Filter by template “family-history” | ~15 prompts found | [ ] |
| 5 | Filter by template “war-service” | ~15 prompts found | [ ] |
| 6 | Verify prompt quality | Thoughtful, engaging questions | [ ] |
| 7 | Verify chapter_title populated | Optional chapter association | [ ] |
Scenario 13.7: Edge Cases and Error Handling
Goal: Test prompt system resilience
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | User with no books | Skipped in cron results | [ ] |
| 2 | User with no email | Skipped in cron results | [ ] |
| 3 | User with invalid email | Error logged but cron continues | [ ] |
| 4 | Resend API failure | Error logged, user marked failed | [ ] |
| 5 | Database connection failure | Cron returns 500 with error details | [ ] |
| 6 | All prompts exhausted for user | Falls back to generic prompts | [ ] |
| 7 | Check cron runs on schedule | Vercel cron: Sundays 10 AM UTC | [ ] |
Part 14: GoalsStep UI Testing
Scenario 14.1: Goals Step Mobile Experience
Goal: Test goals step responsive design
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open wizard on mobile (375px) | Single-column layout | [ ] |
| 2 | Story count buttons | 2x2 grid on mobile | [ ] |
| 3 | Button labels | Short labels: “10”, “15”, “20”, “None” | [ ] |
| 4 | Weekly prompts box | Compact text on mobile | [ ] |
| 5 | Date picker | Full width, accessible | [ ] |
| 6 | Tap targets | Min 44px height on all buttons | [ ] |
Scenario 14.2: Goals Step Desktop Experience
Goal: Test goals step on desktop
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Open wizard on desktop (1024px+) | Centered content, max-width container | [ ] |
| 2 | Story count buttons | 4-column grid | [ ] |
| 3 | Button labels | Full labels: “10 stories”, “15 stories”, etc. | [ ] |
| 4 | Weekly prompts box | Full text with “delivered to your inbox” | [ ] |
| 5 | ”Recommended” badge | Visible on 10 stories option | [ ] |
| 6 | Check mark indicator | Shows on selected option | [ ] |
Scenario 14.3: Goals Step Auto-Population
Goal: Test date auto-population logic
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Wizard loads fresh | 10 stories + date ~10 weeks out | [ ] |
| 2 | Select 15 stories | Date updates to ~15 weeks out | [ ] |
| 3 | Select 20 stories | Date updates to ~20 weeks out | [ ] |
| 4 | Select “No goal” | Date field hides completely | [ ] |
| 5 | Select 10 stories again | Date reappears with ~10 weeks | [ ] |
| 6 | Manually change date | Custom date persists | [ ] |
| 7 | Change story count | Date resets to calculated value | [ ] |
Scenario 14.4: Goals Step Accessibility
Goal: Test goals step keyboard and screen reader
| Step | Action | Expected Result | Pass |
|---|---|---|---|
| 1 | Tab to story count buttons | Focus visible on each | [ ] |
| 2 | Use arrow keys in radio group | Selection moves (if supported) | [ ] |
| 3 | Press Enter/Space on button | Selects the option | [ ] |
| 4 | Screen reader reads group | ”Select story count goal” announced | [ ] |
| 5 | Screen reader reads selection | ”10 stories, Recommended, selected” | [ ] |
| 6 | Focus on date input | Label “Target finish date” announced | [ ] |
Final Sign-Off Checklist
Before marking testing complete:
Core Functionality:
- All critical scenarios (Part 1-6) pass
- Mobile scenarios (Part 9) pass
- At least one full user journey per persona (self/family/gift)
- Permission boundaries tested
- Error handling tested
- No data loss observed
Weekly Story Prompts System (Part 13):
- Cron endpoint authentication works
- Prompt selection algorithm selects appropriate prompts
- Email delivery via Resend works
- User can control prompt frequency in settings
- Prompt delivery log tracks deliveries correctly
- Template-based prompts seeded for all 4 templates
GoalsStep UI (Part 14):
- Auto-population of target date works on initial load
- Date recalculates when story count changes
- Mobile responsive (2x2 grid, short labels)
- Desktop layout (4-column grid, full labels)
- Weekly prompts info box displays correctly
- Keyboard navigation works
Database Migrations:
-
prompt_delivery_logtable exists -
book_chapter_promptstable exists with 60+ seed prompts -
user_prompt_preferencestable exists - RLS policies enforced on all prompt tables
Tester Name: _______________ Date Completed: _______________ Blockers Found: _______________
Appendix A: Environment Variables Required
For testing the weekly prompts system, ensure these are configured:
| Variable | Purpose | Required For |
|---|---|---|
CRON_SECRET | Authenticates cron requests | Scenario 13.1 |
RESEND_API_KEY | Sends emails via Resend | Scenario 13.3 |
NEXT_PUBLIC_APP_URL | Base URL for email links | Scenario 13.3 |
Appendix B: SQL Queries for Verification
Check seeded prompts:
SELECT template_type, COUNT(*)
FROM book_chapter_prompts
GROUP BY template_type;Check prompt delivery log:
SELECT * FROM prompt_delivery_log
WHERE user_id = '[USER_ID]'
ORDER BY delivered_at DESC LIMIT 5;Check eligible users for weekly prompts:
SELECT id, email, email_frequency, email_notifications
FROM profiles
WHERE email_frequency = 'weekly'
AND email_notifications = true
AND email IS NOT NULL;