Admin
Dashboard / Stats
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-001 | View platform overview stats on dashboard | Logged in as Superadmin, at least 1 org exists | 1. Navigate to /admin/dashboard 2. Wait for page to load | Dashboard displays: Total Orgs, Active Trials, Trials Expiring ≤7d, Suspended Accounts, Messages Today cards with correct numbers | High |
| ADM-002 | Dashboard loads stats on mount | Logged in as Superadmin, no manual refresh | 1. Navigate to /admin/dashboard | Stats are fetched automatically; no manual "Refresh" button needed | High |
| ADM-003 | Dashboard shows recent campaign failures | Logged in as Superadmin, at least 1 cancelled campaign with error_message exists | 1. Navigate to /admin/dashboard 2. Scroll to "Recent Campaign Failures" section | Table shows up to 10 cancelled campaigns with: Org name, Campaign name, Error message (truncated to 200 chars), Created timestamp | High |
| ADM-004 | Dashboard shows empty state for campaign failures | Logged in as Superadmin, no failed campaigns exist | 1. Navigate to /admin/dashboard 2. Look at "Recent Campaign Failures" section | "No recent failures" text appears centered | Medium |
| ADM-005 | Trial expiry color coding on dashboard | Logged in as Superadmin | 1. Navigate to /admin/dashboard 2. Observe stat card for "Expiring ≤7d" | Card text is amber (text-amber-600) if count > 0; gray if count = 0 | Medium |
| ADM-006 | Suspended accounts color coding on dashboard | Logged in as Superadmin | 1. Navigate to /admin/dashboard 2. Observe stat card for "Suspended" | Card text is red (text-red-600) if count > 0; gray if count = 0 | Medium |
| ADM-007 | Dashboard shows loading skeleton | Logged in as Superadmin, simulate slow network | 1. Navigate to /admin/dashboard 2. Observe initial render before stats load | 5 skeleton placeholders appear (animate-pulse); replaced by stat cards once data arrives | Medium |
| ADM-008 | Dashboard displays error message if stats fetch fails | Logged in as Superadmin, API returns 500 | 1. Navigate to /admin/dashboard 2. Wait for error | Red error box appears at top with error text | Medium |
Organizations Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-009 | View organizations list | Logged in as Superadmin | 1. Navigate to /admin/organizations | Table displays all orgs with: name, status (active/inactive), trial expiry date, member count, KB usage, Actions | High |
| ADM-010 | Search organizations by name | Logged in as Superadmin, at least 3 orgs exist | 1. Navigate to /admin/organizations 2. Type "test" in search box 3. Press Enter or wait for auto-search | Table filters to show only orgs matching "test"; count updates | High |
| ADM-011 | Pagination on organizations list | Logged in as Superadmin, 25+ orgs exist, page_size=20 | 1. Navigate to /admin/organizations 2. See page 1 with 20 rows 3. Click "Next" or go to page 2 | Page 2 loads showing next 20 orgs; "Previous" button becomes enabled | High |
| ADM-012 | Toggle organization active status | Logged in as Superadmin, org exists with is_active=true | 1. Navigate to /admin/organizations 2. Find org 3. Click toggle/checkbox in "Status" column | Status switches to inactive; toggle switches visually; success toast appears | High |
| ADM-013 | Reactivate inactive organization | Logged in as Superadmin, org with is_active=false exists | 1. Navigate to /admin/organizations 2. Find inactive org 3. Click toggle to reactivate | Status switches to active; toggle switches visually; success toast appears | High |
| ADM-014 | View organization members | Logged in as Superadmin, org with members exists | 1. Navigate to /admin/organizations 2. Click "Members" button on org row | Modal opens showing list of org members with: email, role (admin/member), join date, status | High |
| ADM-015 | Trial expiry color coding in org list | Logged in as Superadmin, org with trial ending in 3 days exists | 1. Navigate to /admin/organizations 2. Look at trial expiry date in table | Expired date shows in red (text-red-600); date ≤7 days from now shows in amber (text-amber-600); date >7 days shows in gray | Medium |
| ADM-016 | KB usage display in org list | Logged in as Superadmin, org has KB configured | 1. Navigate to /admin/organizations 2. Look at KB usage column | Shows: "X / Y documents" where X is total_documents, Y is max_kb_pages; bar shows usage % | Medium |
| ADM-017 | Edit max KB pages for organization | Logged in as Superadmin, org in list | 1. Navigate to /admin/organizations 2. Click on org KB pages field (shows max_kb_pages) 3. Change value to 75 4. Click Save or Confirm | Value updates; PUT /admin/organizations/{orgId}/kb-config sent with max_kb_pages=75; KB stats reflect new limit | Medium |
| ADM-018 | Delete organization with confirmation | Logged in as Superadmin, org named "ToDelete" exists | 1. Navigate to /admin/organizations 2. Click "Delete" button on org row 3. Modal opens asking to confirm by typing org name 4. Type "ToDelete" 5. Click "Confirm Delete" | Org is soft-deleted (deleted_at set); removed from list; success toast shows | High |
| ADM-019 | Delete confirmation requires exact org name | Logged in as Superadmin, org named "ToDelete" with delete modal open | 1. Type "ToDelet" (wrong) in confirm text field 2. Try to click "Confirm Delete" | "Confirm Delete" button is disabled; cannot proceed until exact name entered | High |
| ADM-020 | Cancel delete organization | Logged in as Superadmin, delete modal open | 1. Click "Cancel" or press Escape key | Modal closes; org remains in list | Medium |
| ADM-021 | Organizations list empty state | Logged in as Superadmin, no orgs exist | 1. Navigate to /admin/organizations | Center message shows "No organizations found" | Low |
Users Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-022 | View all users list | Logged in as Superadmin | 1. Navigate to /admin/users | Table displays all users with: email, organization, status (active/suspended), created_at, last_login, Actions | High |
| ADM-023 | Search users by email | Logged in as Superadmin, at least 3 users exist | 1. Navigate to /admin/users 2. Type "john@" in search box 3. Press Enter or auto-search | Table filters to show only users matching "john@" | High |
| ADM-024 | Filter users by status | Logged in as Superadmin, at least 1 active and 1 suspended user | 1. Navigate to /admin/users 2. Select "active" from Status dropdown | Table shows only active users | Medium |
| ADM-025 | Filter users by suspended status | Logged in as Superadmin, suspended users exist | 1. Navigate to /admin/users 2. Select "suspended" from Status dropdown | Table shows only suspended users (is_active=false) | Medium |
| ADM-026 | Paginate users list | Logged in as Superadmin, 25+ users exist | 1. Navigate to /admin/users with page_size=20 2. See page 1 3. Click next | Page 2 loads with next 20 users | Medium |
| ADM-027 | Suspend a user account | Logged in as Superadmin, active user exists | 1. Navigate to /admin/users 2. Find user 3. Click "Suspend" button in Actions | User status changes to "Suspended"; is_active becomes false; user can no longer log in | High |
| ADM-028 | Reactivate a suspended user | Logged in as Superadmin, suspended user exists | 1. Navigate to /admin/users 2. Find suspended user 3. Click "Reactivate" button | User status changes back to "Active"; is_active becomes true; user can log in again | High |
| ADM-029 | Users empty state | Logged in as Superadmin, no users exist | 1. Navigate to /admin/users | Message "No users found" appears | Low |
Subscriptions / Trial Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-030 | View trial subscriptions list | Logged in as Superadmin, at least 1 org in trial | 1. Navigate to /admin/subscriptions | Table shows trial subscriptions with: org name, trial_ends_at, days remaining, Actions | High |
| ADM-031 | Days remaining calculation | Logged in as Superadmin, org trial ending in 5 days | 1. Navigate to /admin/subscriptions 2. Find org in list | Days remaining shows "5d" | Medium |
| ADM-032 | Expired trial shows "Expired" label | Logged in as Superadmin, org with trial_ends_at in past | 1. Navigate to /admin/subscriptions 2. Find expired org | "Expired" label appears in red instead of day count | Medium |
| ADM-033 | Days remaining color: ≤7 days shows amber | Logged in as Superadmin, org trial ending in 4 days | 1. Navigate to /admin/subscriptions 2. Find org | Days cell shows "4d" in amber (text-amber-600) | Medium |
| ADM-034 | Days remaining color: >7 days shows gray | Logged in as Superadmin, org trial ending in 15 days | 1. Navigate to /admin/subscriptions 2. Find org | Days cell shows "15d" in gray (text-gray-600) | Medium |
| ADM-035 | Days remaining color: expired shows red | Logged in as Superadmin, org trial expired | 1. Navigate to /admin/subscriptions 2. Find expired org | "Expired" shows in red (text-red-600) | Medium |
| ADM-036 | Approve trial subscription | Logged in as Superadmin, org with pending subscription (to be confirmed) | 1. Navigate to /admin/subscriptions 2. Click "Approve" button on org row 3. Confirmation modal appears 4. Click "Confirm" | Subscription status changes from "trial" to "active"; org granted paid access; success toast | High |
| ADM-037 | Extend trial by 7 days | Logged in as Superadmin, org in trial | 1. Navigate to /admin/subscriptions 2. Click "Extend" dropdown on org row 3. Select "+7 days" | trial_ends_at extends by 7 days; days remaining recalculates; success toast | High |
| ADM-038 | Extend trial by 14 days | Logged in as Superadmin, org in trial | 1. Navigate to /admin/subscriptions 2. Click "Extend" dropdown 3. Select "+14 days" | trial_ends_at extends by 14 days; success toast | High |
| ADM-039 | Extend trial by 30 days | Logged in as Superadmin, org in trial | 1. Navigate to /admin/subscriptions 2. Click "Extend" dropdown 3. Select "+30 days" | trial_ends_at extends by 30 days; success toast | Medium |
| ADM-040 | Subscriptions empty state | Logged in as Superadmin, no trial orgs exist | 1. Navigate to /admin/subscriptions | "No active trials" message appears | Low |
Template Library: Messages
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-041 | View message templates list | Logged in as Superadmin, at least 1 message template exists | 1. Navigate to /admin/template-library 2. Ensure "Messages" tab is selected | Table shows templates with: name, description, type (text/interactive/media), published status, Actions | High |
| ADM-042 | Open create message template modal | Logged in as Superadmin | 1. Navigate to /admin/template-library (Messages tab) 2. Click "Create Message" button | Modal opens with empty form: name, description, template_type dropdown, content JSON editor, industry_tags, use_case_tags, customization_hints, is_published checkbox | High |
| ADM-043 | Create text message template | Logged in as Superadmin, create modal open | 1. Enter name: "Welcome Message" 2. Enter description: "First touchpoint" 3. Keep template_type as "text" 4. Enter content: `{"body":"Hello {{name}}!"}` 5. Enter industry_tags: "retail, ecommerce" 6. Check is_published 7. Click "Save" | Message template created; modal closes; success toast "Message template created"; appears in list | High |
| ADM-044 | Create interactive message template | Logged in as Superadmin, create modal open | 1. Enter name: "Survey" 2. Select template_type: "interactive" 3. Enter content: `{"type":"list","options":[...]}` 4. Click "Save" | Interactive template created and listed with type badge "Interactive" | Medium |
| ADM-045 | Create media message template | Logged in as Superadmin, create modal open | 1. Enter name: "Product Image" 2. Select template_type: "media" 3. Enter content: `{"type":"image","url":"..."}` 4. Click "Save" | Media template created with type badge "Media" | Medium |
| ADM-046 | Edit message template | Logged in as Superadmin, message template exists | 1. Navigate to /admin/template-library (Messages tab) 2. Click "Edit" on template row | Modal opens with form pre-filled with existing values | High |
| ADM-047 | Update message template name | Logged in as Superadmin, edit modal open with template | 1. Change name from "Welcome" to "Welcome v2" 2. Click "Save" | Template name updated in list; success toast | High |
| ADM-048 | Update message template is_published status | Logged in as Superadmin, edit modal open | 1. Uncheck is_published checkbox 2. Click "Save" | Template is_published set to false; "Published" badge disappears from list | Medium |
| ADM-049 | Validate message template name required | Logged in as Superadmin, create modal open | 1. Leave name empty 2. Click "Save" | Error text appears under name field: "Name is required"; form not submitted | High |
| ADM-050 | Validate message template content JSON | Logged in as Superadmin, create modal open | 1. Enter invalid JSON in content: `{invalid}` 2. Click "Save" | Error text appears: "Invalid JSON in content"; form not submitted | Medium |
| ADM-051 | Delete message template | Logged in as Superadmin, message template exists | 1. Navigate to /admin/template-library (Messages tab) 2. Click "Delete" on template row 3. Confirm deletion in modal | Template deleted; removed from list; success toast | High |
| ADM-052 | Cancel creating message template | Logged in as Superadmin, create modal open with data | 1. Click "Cancel" button or press Escape | Modal closes; no data saved; returns to list | Medium |
| ADM-053 | Message templates empty state | Logged in as Superadmin, no message templates exist | 1. Navigate to /admin/template-library (Messages tab) | "No message templates" message appears | Low |
Template Library: Flows
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-054 | View flow templates list | Logged in as Superadmin, at least 1 flow template exists | 1. Navigate to /admin/template-library 2. Click "Flows" tab | Table shows flows with: name, description, category, published status, Actions | High |
| ADM-055 | Open create flow template modal | Logged in as Superadmin, Flows tab active | 1. Click "Create Flow" button | Modal opens with form: name, description, category dropdown, definition JSON editor, industry_tags, use_case_tags, customization_hints, is_published checkbox | High |
| ADM-056 | Create flow template | Logged in as Superadmin, create flow modal open | 1. Enter name: "Onboarding Flow" 2. Enter description: "New user setup" 3. Select category: "general" 4. Enter definition: `{"nodes":[],"edges":[]}` 5. Enter industry_tags: "saas" 6. Check is_published 7. Click "Save" | Flow template created; modal closes; success toast; appears in Flows list | High |
| ADM-057 | Edit flow template | Logged in as Superadmin, flow template exists | 1. Navigate to /admin/template-library (Flows tab) 2. Click "Edit" on flow row | Modal opens pre-filled with existing values | High |
| ADM-058 | Update flow template category | Logged in as Superadmin, edit flow modal open | 1. Change category from "general" to "customer_service" 2. Click "Save" | Category updated; list reflects change | Medium |
| ADM-059 | View flow template definition | Logged in as Superadmin, flow template in list | 1. Navigate to /admin/template-library (Flows tab) 2. Click "View" button on flow row | Read-only modal opens showing flow definition JSON (likely visual flow diagram, but represented as JSON editor in read-only state) | Medium |
| ADM-060 | Validate flow template name required | Logged in as Superadmin, create flow modal | 1. Leave name empty 2. Click "Save" | Error: "Name is required" under name field; form not submitted | High |
| ADM-061 | Validate flow template definition JSON | Logged in as Superadmin, create flow modal | 1. Enter invalid JSON in definition: `{bad}` 2. Click "Save" | Error: "Invalid JSON in definition"; form not submitted | Medium |
| ADM-062 | Delete flow template | Logged in as Superadmin, flow exists | 1. Navigate to /admin/template-library (Flows tab) 2. Click "Delete" on row 3. Confirm in modal | Flow deleted; removed from list; success toast | High |
| ADM-063 | Cancel creating flow template | Logged in as Superadmin, create flow modal with data | 1. Click "Cancel" or press Escape | Modal closes; no save; returns to Flows tab | Medium |
| ADM-064 | Switch between Messages and Flows tabs | Logged in as Superadmin, on Messages tab | 1. Click "Flows" tab 2. Verify flows load 3. Click "Messages" tab | Content switches; each tab loads and displays its data independently | Medium |
| ADM-065 | Flow templates empty state | Logged in as Superadmin, no flow templates exist | 1. Navigate to /admin/template-library (Flows tab) | "No flow templates" message appears | Low |
Permission & Authorization Boundaries
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-066 | Non-superadmin cannot access /admin/dashboard | Logged in as Agent or Org Admin | 1. Attempt to navigate to /admin/dashboard | Redirect to /401 or /403; "Access Denied" message; not allowed to view platform stats | High |
| ADM-067 | Non-superadmin cannot access /admin/organizations | Logged in as Agent | 1. Attempt to navigate to /admin/organizations | Redirect to /401 or /403; cannot view/manage any orgs | High |
| ADM-068 | Non-superadmin cannot access /admin/users | Logged in as Agent | 1. Attempt to navigate to /admin/users | Redirect to /401 or /403; cannot view/manage users | High |
| ADM-069 | Non-superadmin cannot access /admin/subscriptions | Logged in as Org Admin | 1. Attempt to navigate to /admin/subscriptions | Redirect to /401 or /403; cannot manage trials/subscriptions | High |
| ADM-070 | Non-superadmin cannot access template library | Logged in as Agent | 1. Attempt to navigate to /admin/template-library | Redirect to /401 or /403; cannot create/edit platform templates | High |
| ADM-071 | Superadmin can access all admin panels | Logged in as Superadmin | 1. Navigate to /admin/dashboard 2. Navigate to /admin/organizations 3. Navigate to /admin/users 4. Navigate to /admin/subscriptions 5. Navigate to /admin/template-library | All pages load successfully; no access denial | High |
Error Handling & Edge Cases
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-072 | Handle API error on stats fetch | Logged in as Superadmin, backend returns 500 | 1. Navigate to /admin/dashboard | Error banner displays: "Failed to load stats"; does not crash | Medium |
| ADM-073 | Handle API error on org delete | Logged in as Superadmin, delete fails with 400 | 1. Navigate to /admin/organizations 2. Click Delete on org 3. Confirm delete | Error modal or toast shows: "Failed to delete organization"; org remains in list | Medium |
| ADM-074 | Handle network timeout on organizations list | Logged in as Superadmin, API call times out | 1. Navigate to /admin/organizations | Loading skeleton displays; after timeout, error message appears | Medium |
| ADM-075 | Handle pagination out of range | Logged in as Superadmin, navigate to /admin/users?page=999 | Page request includes invalid page number 999 | Backend returns empty array or 400; frontend shows "No users found" or error message | Low |
| ADM-076 | Organization deletion is soft delete (not hard delete) | Logged in as Superadmin, org deleted | 1. Delete org via UI 2. Check database or audit log | Record marked with deleted_at timestamp; not permanently removed from DB; audit trail preserved | High |
| ADM-077 | Search with special characters | Logged in as Superadmin, org named "Test & Co. Ltd." | 1. Navigate to /admin/organizations 2. Search for "Test & Co." | Search properly escapes and finds org without SQL injection risk | Medium |
| ADM-078 | Case-insensitive search | Logged in as Superadmin, org named "ACME Corp" | 1. Navigate to /admin/organizations 2. Search for "acme corp" (lowercase) | Org found in results | Medium |
| ADM-079 | Handle concurrent subscription extend requests | Logged in as Superadmin, click Extend multiple times rapidly | 1. Navigate to /admin/subscriptions 2. Click "Extend +7d" multiple times quickly | Only one request succeeds; others are debounced/blocked; no duplicate extends | Medium |
| ADM-080 | Keyboard navigation: Escape closes modals | Logged in as Superadmin, any modal open | 1. Press Escape key | Modal closes; focus returns to underlying page | Medium |
Real-time Updates & State Management
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| ADM-081 | Dashboard stats refresh on revisit | Logged in as Superadmin, visit dashboard, then navigate away and back | 1. Navigate to /admin/dashboard 2. Note stat values 3. Navigate to /admin/organizations 4. Return to /admin/dashboard | Stats are re-fetched (not cached); may reflect new data if changed in background | Medium |
| ADM-082 | Org list updates after delete without page reload | Logged in as Superadmin, viewing orgs list | 1. Delete org from list 2. Confirm deletion | Org row disappears from list immediately; no manual refresh needed | High |
| ADM-083 | User status toggle reflects immediately | Logged in as Superadmin, viewing user | 1. Click suspend toggle on user 2. Toggle switches visually 3. Confirm by reloading page | Toggle state reflects in UI immediately; persists after reload | High |