Campaign Groups
Comprehensive manual QA testing plan for the fundraising campaign groups feature (~290 tests).
Context#
Comprehensive manual QA testing plan for the fundraising campaign groups feature. Campaign groups are a parent entity that contain multiple campaigns, either in Aggregated mode (combined metrics) or Split mode (independent campaigns). This plan covers every setting, toggle, field, and interaction — including the split/aggregate mode behavior that disables certain cards.
How to Use This Plan#
- Work through each section sequentially
- For every setting: change it, save, refresh the page, and confirm it persisted
- Where indicated, also check the public campaign group page to confirm the setting is reflected to donors
- Pay special attention to Split vs Aggregate mode — several cards are disabled in Split mode
- Mark each item pass/fail as you go
Key Differences from Campaigns#
| Feature | Campaign | Campaign Group |
|---|---|---|
| Parent entity | Belongs to a Fund | Standalone (no fund) |
| Child entities | None | Contains campaigns array |
| Anonymous supporters | Has enable_anonymous toggle | Not available |
| Supporter comments | Has enable_comments toggle | Not available |
| Zakat field name | is_zakat_eligible | override_zakat_mode (overrides child campaigns) |
| Accept late payments | Has accept_late toggle | Not available |
| External ID | Has external_id field | Not available |
| Amounts tab | Frequencies + Giving Amounts + Intelligence | Intelligence card only |
| Emails tab | 3 receipt types (one-time, recurring, installment) | No Emails tab |
| Split/Aggregate mode | Not applicable | enable_aggregate toggle disables Goal, Supporter Feed, End Date |
| Delete restriction | Cannot delete if raised > 0 | Always deletable |
| Tabs | 8 tabs | 7 tabs (no Emails) |
1. Campaign Groups List Page#
Route: /dashboard/{org}/fundraising/campaign-groups
1.1 Data Table Display#
- Page loads and displays all campaign groups in a table
- Default visible columns: Name, Status, # Campaigns, Raised, % of Goal, Goal, Supporters, Created
- Name column shows internal name, sortable, min-width 350px
- Status chips show correct colors (Published = green, Draft = yellow, Archived = grey)
- # Campaigns column shows count of child campaigns, right-aligned
- Raised column shows correct currency formatting (e.g.,
$1,234.56), right-aligned - % of Goal column shows percentage with color coding:
- < 30%: light blue
- < 70%: medium blue
- > = 70%: dark blue
- Goal column shows correct currency formatting
- Supporters column shows count
- Created column shows formatted date, sortable
1.2 Optional Columns#
- Click column settings and toggle on each optional column one by one:
- ID
- Slug
- End Date
- Mode (displays "Aggregate" or "Split" based on
enable_aggregate) - Most Recent Donation Date
- Zakat Raised
- Average Donation Amount
- Recurring Supporters
- 1 Month Estimated Recurring
- 1 Year Estimated Recurring
- Each column shows correct data
- Column preferences persist after page refresh
1.3 Sorting#
- Created Date (default: descending) — click to toggle asc/desc
- Name — click to sort alphabetically asc/desc
- Amount Raised — click to sort by raised amount
- Number of Campaigns — click to sort by campaign count
- Sorting persists in URL params
- Sort order survives page refresh
1.4 Filtering#
- Created Date: Set a date range filter — table filters correctly
- Status: Toggle Published / Draft / Archived — table filters correctly
- Amount Raised: Set min/max range — filters correctly
- Fundraising Goal: Set min/max range — filters correctly (desktop only)
- Supporter Count: Set min/max range — filters correctly (desktop only)
- Number of Campaigns: Set min/max range — filters correctly
- Combining multiple filters works correctly
- Clearing filters restores full list
- Filter state persists in URL params
1.5 Search#
- Search by campaign group name — matches correctly
- Search by slug — matches correctly
- Search by ID (prefix match) — matches correctly
- Clear search restores full list
1.6 Pagination#
- Pagination controls appear when campaign groups exceed page size
- Navigating pages works correctly
- Page state persists in URL
1.7 Mobile Responsive#
- Resize to mobile width — table switches to card view
- Mobile card shows:
- Title + status chip in header row
- Raised amount + progress bar (if goal exists)
- Campaign count chip in footer
- Status chip in footer
- Actions menu accessible
- Card data matches table data
1.8 Row Actions#
- On a Draft campaign group (with campaigns):
- "Publish" action appears and works (status becomes Published)
- "Edit" navigates to campaign group detail page
- "Copy Link" copies public URL to clipboard
- "Duplicate" opens DuplicateCampaignGroupModal
- "Delete" appears and works
- On a Draft campaign group (with NO campaigns):
- "Publish" action does NOT appear (requires at least 1 campaign)
- All other actions still work
- On a Published campaign group:
- "View" appears and opens public URL in new tab
- "Edit" navigates to detail page
- "Copy Link" works
- "Duplicate" works
- Publish action is NOT shown (already published)
- "Delete" still appears (no raise restriction for groups)
- On an Archived campaign group:
- "Publish" action appears if has campaigns (re-publish)
- "Delete" appears
2. Campaign Group Creation#
2.1 New Campaign Group Modal#
- Click "Add Campaign Group" button — modal opens
- Internal Name field is required — cannot submit empty
- Display Title field (content.title) is present
- No fund selection (campaign groups don't belong to funds)
- No zakat eligible toggle (set later in settings)
- Submit creates campaign group with status DRAFT
- After creation, navigates to the new campaign group's detail page
- New campaign group appears in the list
- Campaign group list cache is invalidated
- Cancel button closes modal without creating
2.2 Duplicate Campaign Group Modal#
- Open duplicate modal from row actions or settings tab
- Shows loading state while fetching source campaign group data
- Pre-fills name as "Copy of {original name}"
- Creates a new DRAFT campaign group with all settings copied
- Verify duplicated campaign group has:
- Same enable_aggregate mode
- Same campaigns array (campaign_id, label, sort_order, override preserved)
- Same goal settings
- Same content (title, message, media) — media passed as ID only
- Same page_content, standpro_content, handheld_content — media as ID only
- Same theme color
- Same zakat settings (override_zakat_mode + zakat_mode)
- Same fees_mode
- Same end_date
- Same thank_you_message
- Same redirect settings
- Same sharing settings
- Same SEO content — media as ID only
- Same intelligence toggles (enable_smart_upsells, enable_smart_amounts)
- Fresh slug (not duplicated from original)
- raised = 0, currency not copied
- Status is DRAFT
- After creation, navigates to the new duplicate's detail page
2.3 Delete Campaign Group Modal#
- Available for ANY campaign group (no raise restriction, unlike campaigns)
- Shows confirmation modal with campaign group internal name
- Shows warning callout: "Any links or widgets pointing to this campaign group will break"
- Confirming deletes the campaign group
- Campaign group disappears from list
- Navigates back to campaign groups list
- Campaign groups list cache is invalidated
- Cancel button closes modal without deleting
3. Campaign Group Detail — Layout & Header#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}
3.1 Header#
- Breadcrumb shows "Campaign Groups" and links back to list
- Campaign group internal name displays in header
- Status chip shows next to name (Published/Draft/Archived)
- Copy Link icon button copies public URL to clipboard
- Draft: "Publish" button appears and works
- Published: "View" button appears and opens public URL in new tab
- Loading spinner shows while fetching campaign group data
- Error state displays if fetch fails
3.2 Footer Progress Bar#
- Aggregate mode + raised > 0 + goal set: Footer shows progress bar
- Displays: "Raised ${amount} | [progress bar] | ${goal} Goal"
- Progress percentage is visually correct
- Aggregate mode + no goal or raised = 0: No footer
- Split mode: No footer regardless of goal/raised
3.3 Tabs#
- All 7 tabs visible: Essentials, Campaign Page, Devices, Amounts, Post Donation, Sharing, Settings
- No Emails tab (campaign groups don't have receipt configuration)
- Clicking each tab navigates to correct route
- Active tab is visually highlighted
- Default tab is Essentials
4. Essentials Tab#
4.1 Main Details Card#
- Internal Name field shows current name
- Change name → Save → Refresh → Name persisted
- Name updates in header after save
- Empty name is rejected (validation)
- Customize Theme Color toggle:
- OFF: No color picker shown, uses org brand_color as default
- ON: Color picker appears with hex input
- Pick a color → Save → Refresh → Color persisted
- Toggle OFF → Save → theme_color is cleared
- Public page check: Theme color reflects on public campaign group page
- No split mode restrictions on this card
4.2 Campaigns Card (Campaign Group-Specific)#
Mode Toggle#
- Segmented control at top: "Aggregated" vs "Split"
- Default mode for new campaign group is Aggregated
- Toggle to Split → Save → Refresh →
enable_aggregate = falsepersisted - Toggle back to Aggregated → Save → Refresh →
enable_aggregate = truepersisted - Switching mode affects other cards immediately (Goal, Supporter Feed, End Date become disabled/enabled)
Campaign List#
- Shows all campaigns currently assigned to this group
- Each campaign row displays:
- Drag handle (grip icon) for reordering
- Label input field (editable, max 40 characters)
- Campaign info chip showing the campaign's internal name
- Delete button to remove campaign from group
- Override Switch (Split mode only):
- Switch appears on each campaign row ONLY when in Split mode
- Switch hidden when in Aggregated mode
- Toggle override ON for a campaign → Save → Refresh → persisted
- Toggle override OFF → Save → Refresh → persisted
Adding Campaigns#
- Click "Add Campaign" button → AddCampaignModal opens
- Modal shows combobox/search for campaigns
- Excluded from list: Campaigns already in this group
- Excluded from list: ARCHIVED campaigns
- Each option shows: internal_name + title as description
- Select a campaign → it's added to the campaigns list
- New campaign appears at end of list with next sort_order
- Label defaults to campaign's internal name (or empty)
- Save → Refresh → new campaign persisted in group
Removing Campaigns#
- Click delete button on a campaign row → campaign removed from list
- Save → Refresh → removal persisted
- Removing all campaigns → Publish button should no longer appear (requires >= 1)
Reordering Campaigns#
- Drag and drop campaigns to reorder
- sort_order values update correctly (0, 1, 2...)
- Save → Refresh → new order persisted
- Public page check: Campaign order on public page matches sort_order
Editing Labels#
- Change campaign label text → Save → Refresh → persisted
- Max 40 characters enforced
- Label displayed on public page (if applicable)
4.3 Goal Card#
- Display Goal toggle:
- OFF: No goal amount input shown
- ON: Goal amount input appears
- Enter goal amount (e.g., 50000) → Save → Refresh → Amount persisted
- Goal shows correct currency symbol
- Footer progress bar updates with new goal (Aggregate mode only)
- Edge cases:
- Amount = 0 when goal enabled → validation error
- Amount > 99,999,999 → validation error
- Negative amount → validation error
Split Mode Behavior#
When in Split mode: Goal card shows "Disabled in Split Mode" badge
Toggle is locked/cannot be changed
Amount input is disabled
Save button is disabled
When switching back to Aggregate mode: Card re-enables, previous values restored
Public page check (Aggregate): Goal and progress bar display on campaign group page
Public page check (Aggregate): Toggling goal OFF hides it from public page
Public page check (Split): No group-level goal shown
4.4 Content Card#
- Media Mode segmented control:
- "Landscape" mode: Shows message + image/video
- "Portrait" mode: Shows image only with title text overlay
- Image Upload:
- Upload an image → Save → Refresh → Image persisted
- Replace image → Save → New image shown
- Remove image → Save → Image removed
- Video URL:
- Enter valid YouTube URL → Save → Refresh → URL persisted
- Enter valid Vimeo URL → works
- Enter invalid URL → validation error
- Display Organization Logo toggle:
- ON → logo shows on campaign group page
- OFF → logo hidden
- Save → Refresh → persisted
- Title (required):
- Enter title → Save → Refresh → persisted
- Clear title → validation error (required)
- Max 50 characters enforced
- Message (rich text, landscape mode only):
- Type message with bold, italic, underline → formatting preserved
- Add bullet list → preserved
- Add link → preserved
- Insert merge tag variable → variable tag shows
- Available merge tags: campaign_group.title, campaign_group.supporter_count, campaign_group.total_raised
- Max 250 characters enforced
- Message hidden in portrait mode
- Title Text Color (portrait mode only):
- Color picker appears for text overlay color
- Pick color → Save → Refresh → persisted
- No split mode restrictions on this card
- Public page check: Content reflects on campaign group page (title, message, media, logo)
5. Campaign Page Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/campaign-page
5.1 Supporter Feed Card#
- Display Supporter Feed toggle:
- ON → Save → Refresh → persisted
- OFF → Save → Refresh → persisted
- Description text mentions "campaign group" (not just "campaign")
Split Mode Behavior#
When in Split mode: Card shows "Disabled in Split Mode" badge
Toggle is locked/cannot be changed
When switching back to Aggregate mode: Card re-enables
Public page check (Aggregate): Supporter feed shows/hides based on toggle
Public page check (Split): No group-level supporter feed
5.2 Content Override Card#
- Override fields are optional — empty means fallback to Essentials content
- Image Override: Upload different image → Save → campaign page uses override image
- Video Override: Enter different video URL → campaign page uses override
- Title Override: Enter custom title → campaign page uses override title
- Message Override: Enter custom message (rich text) → campaign page uses override
- Clear all overrides → Save → campaign page falls back to main content
- No split mode restrictions on this card
- Public page check: Campaign group page shows override content when set, main content when not
6. Devices Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/devices
6.1 StandPro Device Media Card#
- Display Media toggle:
- ON: Image upload area visible
- OFF: Media hidden on StandPro devices
- Upload StandPro-specific image → Save → Refresh → persisted
- Enter StandPro video URL → Save → Refresh → persisted
- Fallback logic:
- If no StandPro media AND content is portrait mode (display_vertical_media = true): falls back to content media
- If no StandPro media AND content is landscape mode: no fallback
- Device check: StandPro device displays correct media
6.2 Handheld Device Media Card#
- Display Media toggle:
- ON: Image upload area visible
- OFF: Media hidden on Handheld devices
- Upload Handheld-specific image → Save → Refresh → persisted
- Enter Handheld video URL → Save → Refresh → persisted
- Fallback logic:
- If no Handheld media AND content is landscape mode (display_vertical_media = false): falls back to content media
- If no Handheld media AND content is portrait mode: no fallback
- Device check: Handheld device displays correct media
7. Amounts Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/amounts
7.1 Intelligence Card#
- Suggest Personalized Upsells toggle:
- ON → "Nizam Intelligence" badge appears → Save → Refresh → persisted
- OFF → Save → Refresh → persisted
- Suggest Personalized Amounts toggle:
- ON → "Nizam Intelligence" badge appears → Save → Refresh → persisted
- OFF → Save → Refresh → persisted
7.2 No Frequencies or Giving Amounts Cards#
- Verify: There is NO Frequencies card on this tab (unlike campaigns)
- Verify: There is NO Giving Amounts card on this tab (unlike campaigns)
- Only the Intelligence card is present
- Campaign groups inherit amounts/frequencies from their child campaigns
8. Post Donation Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/post-donation
8.1 Thank You Card#
- Thank You Message field (rich text):
- Three default quick-select options: "JazakAllah Khair!", "JazakAllah!", "Thank you!"
- Select each option → Save → Refresh → persisted
- Custom rich text message → Save → Refresh → persisted
- Merge tags available: campaign_group.title, campaign_group.supporter_count, campaign_group.total_raised
- Public page check: Correct thank you message shows after donation through group
8.2 Redirect Card#
- Enable Redirect toggle:
- OFF: No redirect settings shown
- ON: URL input + Auto Redirect toggle appear
- Redirect URL:
- Enter valid URL (https://example.com) → Save → Refresh → persisted
- Enter invalid URL → validation error
- Empty URL when enabled → validation error
- Auto Redirect toggle:
- ON: Auto-redirects after donation
- OFF: Shows "Continue" button for manual redirect
- Save → Refresh → persisted
- Public page check: After donation through group, redirect behavior matches setting
8.3 Sharing Channels Card#
- Entity type is "campaign-group" (affects default URL format)
- Enable Sharing Channels toggle:
- OFF: Sharing disabled after donation
- ON: URL + Message inputs appear
- Sharing URL:
- Defaults to:
{baseUrl}/{org-slug}/campaigns/{campaign-group-slug} - Can customize to different URL
- Enter URL → Save → Refresh → persisted
- Defaults to:
- Message:
- Enter sharing message → Save → Refresh → persisted
- Public page check: After donation through group, sharing options show with correct URL and message
9. Sharing Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/sharing
9.1 Slug Card#
- Entity type is "campaign-group"
- Shows current slug with full URL preview
- Change slug to valid kebab-case value → Save → Refresh → persisted
- Invalid characters → validation error
- Empty slug → validation error
- Duplicate slug (already exists for org) → error from server
- Public page check: Campaign group is accessible at the new slug URL
- Public page check: Old slug URL no longer works (or redirects)
9.2 SEO Card#
- Entity type is "campaign-group"
- SEO Title: Enter title → Save → Refresh → persisted
- Placeholder falls back to: page_content.title → content.title → "Write an SEO title"
- SEO Description: Enter description → Save → Refresh → persisted
- Social Image: Upload image → Save → Refresh → persisted
- Falls back to campaign group content image if not set
- Public page check: Share campaign group URL on social media (or use meta tag inspector):
- og:title matches SEO title (or fallback)
- og:description matches SEO description
- og:image matches uploaded social image (or fallback)
10. Settings Tab#
Route: /dashboard/{org}/fundraising/campaign-groups/{id}/settings
10.1 No General Card#
- Verify: There is NO "General" card (no anonymous supporters or comments toggles)
- These settings are controlled at the individual campaign level, not the group level
10.2 No Financial Card#
- Verify: There is NO "Financial" card (no fund selection or external ID)
- Campaign groups don't belong to funds — individual campaigns do
10.3 End Date Card#
- Has End Date toggle:
- OFF: Campaign group runs indefinitely
- ON: Date picker appears
- End Date:
- Select future date → Save → Refresh → persisted
- Cannot select past date (timezone-aware)
- No "Accept Late Payments" toggle (unlike campaigns, campaign groups don't have this)
Split Mode Behavior#
When in Split mode: End Date card shows "Disabled in Split Mode" badge
Toggle is locked/cannot be changed
Date picker is disabled
When switching back to Aggregate mode: Card re-enables
Public page check (Aggregate): Campaign group stops accepting donations after end date
Public page check (Split): End date controlled at individual campaign level
10.4 Zakat Card#
- Title shows as "Override Zakat selection mode" (not just "Zakat")
- Override Zakat Mode toggle (maps to
override_zakat_mode):- OFF: No zakat override — child campaigns use their own zakat settings
- ON: Zakat mode radio group appears, overrides all child campaigns
- Zakat Mode (when override enabled):
- Optional On: Shows zakat checkbox, pre-checked → Save → Refresh → persisted
- Optional Off: Shows zakat checkbox, unchecked → Save → Refresh → persisted
- Required: Always zakat, no checkbox → Save → Refresh → persisted
- Disabled: No zakat option → Save → Refresh → persisted
- Verify data mapping:
is_zakat_eligiblefrom card maps tooverride_zakat_modein the API - Public page check (override ON): Zakat behavior on group page matches selected mode, regardless of individual campaign settings
- Public page check (override OFF): Each campaign within group uses its own zakat setting
10.5 Fees Card#
- Fees Mode radio options:
- Smart (Nizam Intelligence badge) → Save → Refresh → persisted
- Optional On → Save → Refresh → persisted
- Optional Off → Save → Refresh → persisted
- Required → Save → Refresh → persisted
- Disabled → Save → Refresh → persisted
- No split mode restrictions on this card
- Public page check: Fee coverage option behavior on group page matches selected mode
10.6 Other Section (Bottom of Settings)#
- "Duplicate Campaign Group" button → Opens DuplicateCampaignGroupModal (tested in Section 2.2)
- "Delete Campaign Group" button → Opens DeleteCampaignGroupModal (tested in Section 2.3)
- Both buttons always present (no conditional visibility based on raised amount)
11. Split vs Aggregate Mode — Comprehensive Test#
This section tests the complete impact of switching between modes.
11.1 Switch from Aggregate to Split#
- Start with a campaign group in Aggregate mode
- Set up: Enable goal, enable supporter feed, set end date
- Go to Essentials → Campaigns Card → Switch to "Split"
- Save the change
- Verify Essentials tab: Goal card shows "Disabled in Split Mode" badge, toggle locked
- Verify Campaign Page tab: Supporter Feed card shows "Disabled in Split Mode" badge, toggle locked
- Verify Settings tab: End Date card shows "Disabled in Split Mode" badge, toggle locked
- Verify header: Footer progress bar disappears
- Verify Campaigns Card: Override switch now visible on each campaign row
- Verify all other cards (Content, Devices, Amounts Intelligence, Post Donation, Sharing, Fees, Zakat) remain fully functional
11.2 Switch from Split to Aggregate#
- Start with a campaign group in Split mode
- Go to Essentials → Campaigns Card → Switch to "Aggregated"
- Save the change
- Verify Essentials tab: Goal card re-enabled, badge removed
- Verify Campaign Page tab: Supporter Feed card re-enabled, badge removed
- Verify Settings tab: End Date card re-enabled, badge removed
- Verify header: Footer progress bar reappears (if raised > 0 and goal set)
- Verify Campaigns Card: Override switch hidden on campaign rows
- Previously saved values for goal, supporter feed, end date are still intact
11.3 Mode Persistence#
- Switch to Split → Save → Refresh page → Still in Split mode
- Switch to Aggregate → Save → Refresh page → Still in Aggregate mode
- Go to list page → Mode column shows correct value ("Split" or "Aggregate")
12. Cross-Cutting Concerns#
12.1 Save Behavior#
- Every card shows unsaved changes indicator when modified
- Save button is disabled until changes are made
- Saving shows loading state (spinner/disabled button)
- Success toast appears after save
- Error toast appears on failure with descriptive message
- Concurrent saves are prevented (second save blocked while first is in-flight)
- Navigating away with unsaved changes — expected behavior (warning or silent discard?)
12.2 Loading States#
- Campaign group detail shows loading spinner while fetching
- Individual cards show skeleton/loading states
- Campaign groups list shows loading state while fetching
12.3 Error Handling#
- Network error during save → error toast, form data not lost
- Network error during load → error state displayed with retry option
- Server validation error → error message displayed to user
12.4 URL State Persistence#
- Campaign groups list: filters, sort, pagination, search persist in URL params
- Copy/paste URL with params → same view loads
- Browser back/forward navigates between filter states
12.5 Campaign Group Status Lifecycle#
- Create campaign group → status is DRAFT
- Add at least 1 campaign → Publish button appears
- Publish draft campaign group → status becomes PUBLISHED
- Remove all campaigns from a DRAFT group → Publish button disappears
- Delete campaign group → group removed entirely (no raise restriction)
12.6 Data Consistency (List ↔ Detail)#
- Edit campaign group name → list reflects new name without full page refresh
- Change status → list status chip updates
- Change goal → list goal column updates
- Add/remove campaigns → list # Campaigns column updates
- Change mode → list Mode column updates (if visible)
12.7 Rich Text Editor#
- Bold, italic, underline formatting saves and loads correctly
- Links save and load correctly (clickable in preview)
- Bullet/numbered lists save and load correctly
- Merge tag variables insert and display correctly as chips/tags
{campaign_group.title}inserts correctly{campaign_group.supporter_count}inserts correctly{campaign_group.total_raised}inserts correctly
- Character limits enforced where specified (50 for title, 250 for message)
- Copy-paste from external sources doesn't break formatting
12.8 Media Upload#
- Image upload works for all image fields (content, page, device, SEO)
- Image preview displays after upload
- Replace existing image works
- Remove image works
- Video URLs (YouTube, Vimeo) validate and display correctly
- Invalid video URLs show validation error
13. End-to-End Donation Flow#
13.1 Aggregate Mode — Full Donor Journey#
- Create a new campaign group
- Set mode to Aggregated
- Add 2-3 published campaigns to the group
- Configure: goal, content (title, message, media), theme color
- Configure: thank you message, sharing channels, SEO
- Configure: fees mode, zakat override
- Enable supporter feed
- Publish the campaign group
- Open the public campaign group URL
- Verify: Theme color, title, message, media, logo all match dashboard settings
- Verify: Child campaigns are listed and selectable
- Verify: Campaign order matches sort_order from dashboard
- Verify: Group-level goal and progress bar display correctly
- Verify: Supporter feed shows (if enabled)
- Verify: Zakat option matches override mode (or falls back to campaign setting)
- Verify: Fee coverage option matches group fee mode
- Select a campaign and complete a donation
- Verify: Thank you message matches group setting
- Verify: Sharing options show with correct URL and message
- Verify: Redirect behavior matches setting
- Verify: Group raised amount increments in dashboard
- Verify: Group supporter count increments
- Verify: The correct child campaign also shows updated raised amount
- Verify: Supporter appears in group feed (if enabled)
13.2 Split Mode — Full Donor Journey#
- Create a campaign group
- Set mode to Split
- Add 2-3 published campaigns
- Configure override switches for some campaigns
- Configure: content, theme color (group-level)
- Publish the campaign group
- Open the public campaign group URL
- Verify: Child campaigns are listed
- Verify: NO group-level goal or progress bar
- Verify: NO group-level supporter feed
- Verify: Each campaign shows its own goal/amounts (not group-level)
- Verify: Campaigns with override ON show group content; override OFF show their own content
- Select a campaign and complete a donation
- Verify: Donation goes to the selected campaign
- Verify: Campaign's own thank you/receipt settings apply (not group-level for overridden settings)
13.3 Edge Cases#
- Campaign group with only 1 campaign — still functions correctly
- Campaign group with a mix of Published and Draft child campaigns — only Published show on public page
- Remove all campaigns from a Published group — what happens on public page? (should show empty or error)
- Archive a child campaign that's in a group — verify it's removed or hidden from public group page
- Change a campaign's fund while it's in a group — no impact on group (groups don't have funds)
Verification Checklist#
| Area | Total Tests | Pass | Fail | Notes |
|---|---|---|---|---|
| Campaign Groups List | ~40 | |||
| Creation/Duplication/Deletion | ~25 | |||
| Layout & Header | ~15 | |||
| Essentials Tab (incl. Campaigns Card) | ~50 | |||
| Campaign Page Tab | ~12 | |||
| Devices Tab | ~12 | |||
| Amounts Tab | ~6 | |||
| Post Donation Tab | ~15 | |||
| Sharing Tab | ~12 | |||
| Settings Tab | ~25 | |||
| Split vs Aggregate Mode | ~20 | |||
| Cross-Cutting | ~25 | |||
| E2E Flows | ~30 | |||
| TOTAL | ~290 |