Device Templates
Comprehensive manual QA testing plan for device templates — configuration presets for devices (~160 tests).
Context#
Comprehensive manual QA testing plan for device templates — configuration presets applied to devices that define which campaign content to show, the checkout experience, and the maximum donation amount. Templates link to a published Campaign or Campaign Group as their content source and provide fallback content for when the primary content is unavailable.
How to Use This Plan#
- Work through each section sequentially
- For every setting: change it, save, refresh the page, and confirm it persisted
- Mark each item pass/fail as you go
- Pre-requisites: At least 1 published campaign and 1 published campaign group should exist
Key Concepts#
| Concept | Details |
|---|---|
| Content Source | Each template references a Campaign (ID prefix fc) or Campaign Group (ID prefix fcg) |
| Checkout Mode | EXPRESS, QUICK, or STANDARD — controls the donor checkout flow on the device |
| Maximum Donation | Currency-aware cap on single donation amount (stored in cents, displayed in dollars) |
| Fallback Content | Title + message shown on devices when the primary campaign content is unavailable |
| Linked Devices | Devices using this template inherit its configuration |
1. Device Templates List Page#
Route: /dashboard/{org}/devices/templates
1.1 Data Table Display#
- Page loads and displays all device templates in a table
- Columns visible:
- Name — sortable, title variant
- Devices — device count using this template, right-aligned, sortable
- Content — resolved name of the linked campaign/campaign group, sortable
- Content ID — raw content ID string, sortable
- Checkout Mode — formatted as "Express", "Quick", or "Standard", sortable
- Created — formatted date, sortable
- ID — template identifier
- All column data matches expected values for each template
- Content column shows resolved campaign/campaign group name (not raw ID)
- Content name resolution handles:
- Campaign IDs (prefix
fc) → shows campaign internal_name - Campaign Group IDs (prefix
fcg) → shows campaign group internal_name - Missing/deleted content → shows "-"
- Campaign IDs (prefix
1.2 Sorting#
- Default sort: Device Count (descending)
- Name — click to sort alphabetically asc/desc
- Devices — click to sort by device count
- Created Date — click to sort by creation date
- Sorting persists in URL params
- Sort order survives page refresh
1.3 Filtering#
- Device Count (range filter):
- Set min device count → filters correctly
- Set max device count → filters correctly
- Set both → range filter works
- Clearing filter restores full list
- Filter state persists in URL params
1.4 Search#
- Search by template name — matches correctly (partial match)
- Search by content name (resolved) — matches correctly
- Search by template ID — matches correctly (prefix match)
- Search by content ID — matches correctly (prefix match)
- Clear search restores full list
- Search works in combination with filters
1.5 Pagination#
- Pagination controls appear when templates exceed page size
- Page size options: 20, 50, 100
- Navigating pages works correctly
- Page state persists in URL
1.6 Mobile Responsive#
- Resize to mobile width — table switches to card view
- Mobile card shows:
- Template name
- Content name (resolved via
useResolveContentNamehook) - Device count chip (info variant)
- Skeleton loading state shows while data fetches
- Actions are accessible on mobile cards
1.7 Row Actions#
- Edit → navigates to template detail page
- Delete → opens DeleteTemplateModal
1.8 Empty States#
- No templates: Shows empty state with "Create new template" button
- Filters applied, no results: Shows filter empty state with "Clear Filters" button
- Error loading: Shows error state with retry button
1.9 Add Template Button#
- "Add Template" button visible at top of page
- Clicking opens NewTemplateModal
2. Device Template Creation#
2.1 New Template Modal#
- Click "Add Template" button — modal opens
- Name field:
- Required — cannot submit empty
- Max 40 characters enforced
- Placeholder: "Enter template name"
- Content field (combobox):
- Required — cannot submit without selection
- Shows loading spinner while campaigns/groups are fetching
- Campaign Groups section shown first (with "Campaign Groups" header)
- Campaigns section shown below (with "Campaigns" header)
- Only PUBLISHED campaigns and campaign groups are available
- Draft/Archived campaigns do NOT appear
- Search within combobox filters options
- Each option shows: internal_name + title as description
- Checkout Mode field (dropdown):
- Required — defaults to EXPRESS
- Options: Express, Quick, Standard
- All three options selectable
- No maximum donation amount field in creation modal (set on detail page)
- No fallback content fields in creation modal (set on detail page)
- Create button:
- Disabled until name AND content are provided
- Shows loading state during submission
- Cannot close modal during submission
- On success:
- Modal closes
- Device templates list cache invalidated
- Navigates to new template's detail page
- New template appears in templates list
- Cancel button closes modal without creating
3. Device Template Detail Page#
Route: /dashboard/{org}/devices/templates/{templateId}
3.1 Header#
- Template name displays as title
- Breadcrumb links back to "Templates" list
- No footer (templates don't track raised amounts)
3.2 Main Details Card (Editable)#
Name Field#
- Shows current template name
- Change name → Save → Refresh → Name persisted
- Name updates in header after save
- Name updates in templates list
- Empty name → validation error (save disabled)
- Max 40 characters enforced
Content Field (Combobox)#
- Shows currently selected content (campaign or campaign group name)
- Click to open combobox dropdown
- Campaign Groups section shown first (with header)
- Campaigns section shown below (with header)
- Only PUBLISHED campaigns and campaign groups available
- Search within combobox filters options by name
- Select a different campaign → field updates
- Select a campaign group → field updates
- Change content → Save → Refresh → New content persisted
- Content column in templates list updates with new resolved name
- Error: "Content is required" if cleared/empty
Checkout Mode Field (Dropdown)#
- Shows current checkout mode
- Options: Express, Quick, Standard
- Change mode → Save → Refresh → Mode persisted
- Mode column in templates list updates
- Device behavior check: Checkout mode affects the donation flow on physical devices
Maximum Donation Amount Field#
- Shows current maximum donation amount with currency symbol prefix
- Formatted with comma separators (e.g.,
$1,000) - Required — cannot save without a value
- Enter amount → Save → Refresh → Amount persisted
- Validation:
- Empty → "Amount is required" error
- Amount = 0 → validation error
- Amount > 100,000 → "Cannot exceed {currency}100,000" error
- Negative amount → validation error
- Currency handling:
- Currency symbol matches template's currency
- Value stored in cents (multiplied by currency multiplier on save)
- Value displayed in dollars (divided by currency multiplier on load)
- Different currencies use correct multipliers
Save Behavior#
- Save button disabled until changes are made
- Save button disabled if validation fails
- Saving shows loading state
- Success toast appears after save
- Error toast appears on failure
- Device templates cache invalidated after save
3.3 Fallback Content Card (Editable — Independent Save)#
- Description: "Set the fallback title and message shown when the primary campaign content is unavailable."
- Title field:
- Text input, optional
- Placeholder: "Enter fallback title"
- Enter title → Save → Refresh → Title persisted
- Clear title → Save → Refresh → Title cleared
- Message field:
- Textarea, 3 rows, optional
- Placeholder: "Enter fallback message"
- Enter message → Save → Refresh → Message persisted
- Clear message → Save → Refresh → Message cleared
- Both fields optional — can save with both empty
- Independent save: This card has its own Save button, separate from Main Details
- Changing fallback content does NOT enable Main Details save button
- Saving fallback content does NOT affect Main Details card
- Both cards can be saved independently
- Save button disabled until changes are made
- Success toast appears after save
- Device templates cache invalidated after save
- Device behavior check: When primary campaign content is unavailable, device shows fallback title + message
3.4 Linked Devices Card (Read-Only)#
- Card title shows: "Linked Devices ({count})"
- Displays first 5 devices as clickable links to device detail pages
- Each link shows device name
- If > 5 devices: "See all" link appears → navigates to devices list filtered by this template (
/devices?template={templateId}) - If 0 devices: Empty state message with link to Devices page
- Device links navigate to correct device detail pages
- Count matches actual number of devices using this template
3.5 Delete Template Card#
- Description/warning: "Ensure no devices are using this template before deleting."
- Delete button is red/destructive
- Clicking opens DeleteTemplateModal
4. Device Template Deletion#
4.1 Delete Template Modal#
- Shows template name (read-only)
- Destructive warning: "Ensure no devices are using this template before deleting."
- Delete button is red/destructive
- Shows loading state during deletion
- Cannot close modal during deletion
- On success:
- Success toast: "Template deleted"
- Device templates list cache invalidated
- Navigates back to templates list (or triggers onSuccess callback)
- Template disappears from list
- Cancel button closes modal without deleting
4.2 Deletion Edge Cases#
- Delete template with 0 linked devices → clean deletion
- Delete template with linked devices → what happens?
- Server may reject deletion (verify behavior)
- Or devices become orphaned (need re-assignment)
- Verify the warning message guides user correctly
- Try to navigate to a deleted template's URL → appropriate error/redirect
5. Content Resolution#
5.1 useResolveContentName Hook#
- Template linked to a Campaign → Content column shows campaign's internal_name
- Template linked to a Campaign Group → Content column shows campaign group's internal_name
- Template linked to deleted/non-existent content → shows "-"
- Content name resolution works in:
- Templates list page (Content column)
- Template mobile card (Content name)
- Template detail page (Content combobox selected value)
5.2 Content Availability#
- Only PUBLISHED campaigns appear in content combobox
- Only PUBLISHED campaign groups appear in content combobox
- DRAFT campaigns do NOT appear
- ARCHIVED campaigns do NOT appear
- DRAFT campaign groups do NOT appear
- ARCHIVED campaign groups do NOT appear
- If a campaign is unpublished after being assigned:
- Template still references it (content_id unchanged)
- Content name may show as "-" or the original name
- Fallback content should display on devices
6. Template-Device Relationship#
6.1 Assigning Templates to Devices#
- Go to a device's detail page
- Change the Template dropdown to a different template → Save
- Verify: Device now appears in new template's linked devices
- Verify: Device removed from previous template's linked devices
- Verify: Devices list shows new template chip for this device
6.2 Template Configuration Inheritance#
- Change template's content → all linked devices now serve new content
- Change template's checkout mode → all linked devices use new checkout flow
- Change template's max donation → all linked devices enforce new limit
- Change template's fallback content → all linked devices use new fallback
- Verify: No per-device override needed — template changes propagate automatically
6.3 Template Chip Display#
- Device assigned to template → DeviceTemplateChip shows template name + icon
- Template name change → chip updates across devices list
- Template not found → chip shows "-"
7. Cross-Cutting Concerns#
7.1 Save Behavior#
- Both cards (Main Details + Fallback Content) have independent save buttons
- Each save button disabled until its own card has changes
- Each save button disabled if its own card has validation errors
- Saving shows loading state (spinner/disabled)
- Success toast appears after save
- Error toast appears on failure
- Form data not lost on error
7.2 Loading States#
- Templates list shows loading state while fetching
- Template detail page shows loading state while fetching
- Content combobox shows loading spinner while campaigns/groups load
- Linked devices card shows loading state
7.3 Error Handling#
- Network error during save → error toast
- Network error during load → error state with retry
- Server validation error → displayed to user
7.4 URL State Persistence#
- Templates list: filters, sort, pagination, search persist in URL params
- Copy/paste URL with params → same view loads
- Browser back/forward navigates between filter states
7.5 Data Consistency#
- Create template → appears in templates list immediately
- Edit template name → list reflects new name
- Edit template content → list content column updates
- Edit template checkout mode → list checkout mode column updates
- Delete template → disappears from list
- Device assigned to template → linked devices count increments
- Device unassigned from template → linked devices count decrements
7.6 Mobile Responsiveness#
- List page renders as cards on mobile
- Detail page stacks cards vertically on mobile
- Combobox dropdown works on mobile
- Modal displays correctly on mobile
8. End-to-End Flows#
8.1 Create Template and Assign to Device#
- Click "Add Template" → modal opens
- Enter template name (e.g., "Lobby Express Checkout")
- Select a published campaign as content
- Set checkout mode to "Express"
- Submit → redirected to new template detail page
- Set maximum donation amount (e.g., $5,000) → Save
- Set fallback content (title: "Welcome", message: "Please try again shortly") → Save
- Go to a device's detail page → change template to "Lobby Express Checkout" → Save
- Go back to template detail page
- Verify: Device appears in linked devices card
- Verify: Device count is 1
- Go to devices list → verify device shows "Lobby Express Checkout" template chip
8.2 Change Template Content Source#
- Open a template detail page
- Note the current content (e.g., Campaign A)
- Change content to a Campaign Group
- Save → verify success
- Verify: Content column in templates list shows campaign group name
- Verify: Linked devices now serve campaign group content (check on device if possible)
8.3 Fallback Content Verification#
- Create a template linked to a published campaign
- Set fallback content (title + message)
- Unpublish/archive the campaign
- Verify: Devices using this template should show fallback content
- Re-publish the campaign
- Verify: Devices go back to showing campaign content
8.4 Template Deletion Flow#
- Create a template with no devices assigned
- Delete via detail page → verify clean deletion
- Create another template and assign 1 device to it
- Try to delete → verify warning about ensuring no devices use it
- Reassign the device to a different template
- Delete the now-empty template → verify clean deletion
8.5 Content Combobox Behavior#
- Create a template → open content combobox
- Verify: Campaign Groups section appears first (if any exist)
- Verify: Campaigns section appears below
- Verify: Only PUBLISHED campaigns/groups shown
- Create a new draft campaign → verify it does NOT appear in combobox
- Publish the campaign → refresh → verify it now appears in combobox
- Archive a campaign that was available → refresh → verify it disappears from combobox
8.6 Maximum Donation Amount Currency Handling#
- Open a template with USD currency
- Set max donation to $500 → Save
- Verify: Display shows "$500" (with currency symbol)
- Verify: Stored value is 50000 (in cents — check via API or refresh)
- Set max donation to $100,000 → Save → verify it accepts
- Set max donation to $100,001 → verify validation error
- Set max donation to $0 → verify validation error
8.7 Edge Cases#
- Template name at max length (40 chars) → saves and displays correctly
- Template with no fallback content → saves correctly (both fields empty)
- Multiple templates linked to the same campaign → both work independently
- Delete a campaign that's linked to a template → template still exists, content shows "-"
- Template with 0 devices → all operations work normally
Verification Checklist#
| Area | Total Tests | Pass | Fail | Notes |
|---|---|---|---|---|
| Templates List Page | ~25 | |||
| Template Creation | ~18 | |||
| Template Detail (Main) | ~30 | |||
| Template Detail (Fallback) | ~12 | |||
| Template Deletion | ~8 | |||
| Content Resolution | ~12 | |||
| Template-Device Relationship | ~10 | |||
| Cross-Cutting | ~15 | |||
| E2E Flows | ~30 | |||
| TOTAL | ~160 |