Campaigns Recently Changed
Campaign List & Filtering
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-001 | View campaigns list on initial load | Logged in as Agent, organization has 3 campaigns in various statuses (draft, running, completed) | 1. Navigate to /campaigns/broadcasts (or /campaigns, which redirects) 2. Wait for page to load | Campaigns list displays with name, WhatsApp account, status, recipient counts, and timestamps. Default broadcasts tab at /campaigns/broadcasts. List enriched with real-time counts and account details. | High |
| CAM-002 | Filter campaigns by status | Logged in as Agent, campaigns list loaded with mix of statuses | 1. Click status dropdown filter 2. Select 'running' | Only campaigns with 'running' status display. Other statuses are hidden. | High |
| CAM-003 | Pagination of campaigns list | Logged in as Agent, organization has 75 campaigns | 1. Navigate to /campaigns 2. Scroll to bottom 3. Observe pagination controls | Default page size is 50. Next page button appears. Page 2 shows campaigns 51-75. | Medium |
| CAM-004 | Empty campaigns list state | Logged in as Agent, no campaigns exist in organization | 1. Navigate to /campaigns | Empty state message displays: "No campaigns yet. Create your first campaign." Create button is visible. | Medium |
| CAM-005 | Search/filter campaigns (future enhancement placeholder) | Logged in as Agent, campaigns list loaded | 1. Navigate to /campaigns | List displays campaigns; search box present in UI for future use | Low |
Campaign Creation - Setup Step
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-006 | Open create campaign wizard | Logged in as Agent, at least one WhatsApp account connected, at least one template available | 1. Navigate to /campaigns 2. Click 'New Campaign' button (Plus icon) | Wizard opens at Step 1/4 (Setup). Modal title shows "Create Campaign". Form fields visible: Name, WhatsApp Account, Template, Campaign Type (Standard/Paced/Autopilot toggle). WizardStepper component displays step progress (1/4). | High |
| CAM-007 | Campaign name validation - required field | In campaign wizard Step 1 | 1. Leave Name field empty 2. Try to proceed to next step | Error message displays under Name field: "Campaign name is required." Next button is disabled or shows error. | High |
| CAM-008 | Campaign name validation - max length | In campaign wizard Step 1 | 1. Enter 256+ character string in Name field 2. Blur field | Error message displays: "Campaign name must be 255 characters or less." | Medium |
| CAM-009 | Select WhatsApp account - required field | In campaign wizard Step 1, multiple accounts available | 1. Leave WhatsApp Account dropdown unselected 2. Try to proceed | Error message displays: "WhatsApp account is required." Next button disabled. | High |
| CAM-010 | Select template - required field | In campaign wizard Step 1, templates available | 1. Leave Template dropdown unselected 2. Try to proceed | Error message displays: "Template is required." Next button disabled. | High |
| CAM-011 | Populate campaign setup form - happy path (standard) | In campaign wizard Step 1, one account and one template available, standard mode selected | 1. Enter Name: "Q2 Product Launch" 2. Select WhatsApp Account from dropdown 3. Select Template from dropdown 4. Ensure "Standard" send mode selected 5. Click Next | Form validation passes. Wizard advances to Step 2 (Recipients). Selected values remain in memory if user returns. | High |
| CAM-012 | Template selector shows only templates for selected account | In campaign wizard Step 1, Account A has 2 templates, Account B has 1 template | 1. Select Account A in dropdown 2. Open Template dropdown 3. Count templates 4. Switch to Account B 5. Open Template dropdown again | Template dropdown initially shows templates for Account A. After switching accounts, only Account B's template appears. | Medium |
| CAM-013 | Navigation - back from Step 1 | In campaign wizard Step 1 with form partially filled | 1. Click X or Back button | Wizard closes. User returns to campaigns list. Form data is discarded (new attempt starts fresh). | Medium |
| CAM-102 | Campaign type selector - Standard mode | In campaign wizard Step 1 | 1. Observe Campaign Type toggle/selector 2. Select "Standard" | Standard send mode selected. Recipients step will show Contacts/Tags/CSV options. is_continuous=false set. | High |
| CAM-103 | Campaign type selector - Paced mode | In campaign wizard Step 1 | 1. Click Campaign Type selector 2. Select "Paced" | Paced mode selected. Daily limit input field appears. Recipients picker available. is_continuous=false, daily_limit field ready. | High |
| CAM-104 | Campaign type selector - Autopilot mode | In campaign wizard Step 1 | 1. Click Campaign Type selector 2. Select "Autopilot" | Autopilot/Continuous mode selected. Recipients step shows only smart segment builder (no contacts/tags/csv). is_continuous=true set. Frequency cap field visible for setting cap_days. | High |
| CAM-149 | Default WhatsApp account selection on wizard open | Logged in as Agent, organization has default_whatsapp_account_id set to Account A, multiple accounts available, Step 1 not yet filled | 1. Open New Campaign wizard 2. Observe WhatsApp Account dropdown on first load | WhatsApp Account dropdown pre-selects the organization's default account (Account A) automatically. User can override by selecting a different account. If no default set, first account in list selected. | High |
| CAM-150 | Default WhatsApp account with single account organization | Logged in as Agent, organization has only one WhatsApp account, no default explicitly set | 1. Open New Campaign wizard 2. Observe WhatsApp Account dropdown | WhatsApp Account dropdown pre-selects the only available account automatically. User cannot change it. | Medium |
Campaign Creation - Recipients Step
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-014 | Recipients step loads with source selection (standard/paced) | In campaign wizard Step 2, setup step completed, standard or paced mode selected | 1. Arrive at Step 2/4 2. Observe recipient source options | Pill buttons: "Filter Contacts (Build Segment)", "Target by Tags", "Upload a CSV List". Default is segment/filter. Helper text explains tags vs rules. | High |
| CAM-015 | Recipients source - segment drawer | In campaign wizard Step 2, standard mode | 1. Click "Filter Contacts (Build Segment)" 2. Configure rules in drawer 3. Click Done | Audience rules summary card shows chips. Drawer has AND/OR toggle, Add rule, inactivity filter. Next enabled when ≥1 valid rule. | High |
| CAM-016 | Recipients source - Tags | In campaign wizard Step 2, at least 3 tags exist with contacts tagged, standard mode | 1. Click "Target by Tags" pill 2. Observe tag picker | Label "Contact has any of these tags", #tag pills with checkmarks, campaign enroll copy. Estimated audience updates. | High |
| CAM-017 | Recipients source - CSV upload | In campaign wizard Step 2, standard or paced mode | 1. Click "Upload a CSV List" pill 2. Observe upload UI | Upload area displays with file picker. Instructions show expected CSV columns (phone, name, template params). | High |
| CAM-018 | CSV upload validation - valid file | In campaign wizard Step 2, CSV source selected | 1. Prepare valid CSV: "phone,name,param1\n+1234567890,John,value1\n+9876543210,Jane,value2" 2. Upload file | File is parsed successfully. Preview table displays 2 rows with phone, name, and param1. "Next" button enabled. | High |
| CAM-019 | CSV upload validation - missing phone column | In campaign wizard Step 2, CSV source selected | 1. Prepare CSV without phone column: "name,email\nJohn,john@example.com" 2. Upload file | Error message displays: "CSV must contain 'phone' and 'name' columns." File is rejected. Upload area remains empty. | High |
| CAM-020 | CSV upload validation - invalid phone format | In campaign wizard Step 2, CSV source selected | 1. Prepare CSV with invalid phone: "phone,name\ninvalid123,John" 2. Upload file | Warning displays: "Row 1: Invalid phone number 'invalid123'. Only rows with valid E.164 format will be included." Processing continues with valid rows. | Medium |
| CAM-021 | CSV upload validation - duplicate phones | In campaign wizard Step 2, CSV source selected | 1. Prepare CSV with duplicate: "phone,name\n+1234567890,John\n+1234567890,John2" 2. Upload file | Duplicate rows shown in preview. Notice: "1 duplicate phone number excluded. 1 unique recipient." File uploads; duplicates removed. | Medium |
| CAM-022 | CSV upload validation - opted_in column filtering | In campaign wizard Step 2, CSV source selected | 1. Prepare CSV with opted_in column: "phone,name,opted_in\n+1234567890,John,true\n+9876543210,Jane,false" 2. Upload file | File parsed. Only rows with opted_in=true or opted_in=1 included in preview (1 recipient). Opted-out rows excluded. | Medium |
| CAM-023 | Recipients validation - segment rules incomplete | In campaign wizard Step 2, segment selected | 1. Open segment drawer 2. Add rule without value 3. Try Next | Next button disabled until all rules have values. | High |
| CAM-023b | Legacy manual contacts draft | Draft campaign with recipient_source=contacts | 1. Edit draft 2. Open Step 2 | Amber banner: manual selection no longer supported. Next disabled until tags, segment, or CSV chosen. | High |
| CAM-024 | Recipients validation - no tags selected | In campaign wizard Step 2, standard mode | 1. Select "Tags" source 2. Don't check any tags 3. Try to proceed | Error message displays: "Please select at least one tag." Next button disabled. | High |
| CAM-025 | Recipient count summary updates | In campaign wizard Step 2, tags or segment selected | 1. Configure audience 2. Observe "Estimated Target Audience" badge | Badge shows preflight count (e.g. "42 contacts") and updates when rules/tags change. | Medium |
| CAM-026 | Navigation - back from Step 2 | In campaign wizard Step 2 with recipients selected | 1. Click Back button | Wizard returns to Step 1. Setup form values retained (name, account, template). | Medium |
| CAM-027 | Navigation - back to Step 2 after review | In campaign wizard Step 3/4 (Customize or Review) | 1. Click Back button | Wizard returns to Step 2. Recipient selections retained. | Medium |
| CAM-105 | Autopilot recipients - segment only | In campaign wizard Step 2, autopilot mode selected | 1. Observe recipient selection UI | Only "Filter Contacts (Build Segment)" pill (tags/CSV hidden). Summary card + drawer for rules; AND/OR in drawer. Frequency cap field visible in segment config. | High |
| CAM-106 | Smart segment - AND operator | Autopilot segment builder on Step 2 | 1. Add rule: "tag = vip" 2. Add rule: "status = active" 3. Set operator to AND 4. Observe condition count | Segment saved with conditions_operator=AND. Preflight estimates recipients matching BOTH rules. | High |
| CAM-107 | Smart segment - OR operator | Autopilot segment builder on Step 2 | 1. Add rule: "tag = vip" 2. Add rule: "tag = leads" 3. Set operator to OR | Segment saved with conditions_operator=OR. Preflight estimates recipients matching EITHER rule (union count). | High |
| CAM-108 | Paced daily limit input | Paced mode selected, Step 2 | 1. Observe daily limit field 2. Enter 50 3. Select recipients | daily_limit=50 stored. Field validated: numeric, positive, ≤10000. Recipients picker available alongside limit. | High |
| CAM-136 | Autopilot frequency cap input | Autopilot mode selected, Step 2 smart segment drawer | 1. Observe frequency_cap_days field 2. Enter 7 3. Click Save | frequency_cap_days=7 stored in smart_rules. Field validated: integer, ≥1, ≤365. Segment rules saved with cap. | High |
| CAM-137 | Frequency cap validation - invalid input | Autopilot segment builder, frequency_cap_days input | 1. Enter 0, -1, or 366 in frequency_cap_days field 2. Try to save segment | Error message displays: "Frequency cap must be between 1 and 365 days." Save button disabled until corrected. | Medium |
Campaign Creation - Customize & Preview Step (4-Step Wizard)
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-109 | Customize step shows template preview | In campaign wizard Step 3/4, setup and recipients completed | 1. Arrive at Step 3/4 2. Observe template preview area | Template body and buttons displayed with sample text and variables highlighted (e.g., {{1}}, {{2}}). Allows review before sending. | High |
| CAM-110 | Variable mapping display (CSV parameters) | Step 3/4, CSV recipients with params: param1, param2 | 1. Observe variable mapping UI 2. See dropdown assignments | TemplateParamMappingEditor component displays. Dropdowns show: "param1 → {{1}}", "param2 → {{2}}" etc. User can reorder/remap if needed. | Medium |
| CAM-111 | Media header preview | Step 3/4, template has IMAGE header | 1. Observe template preview 2. Scroll to header section | Header media component shown (thumbnail if image). "header_media_id" field or media selector visible. | Medium |
| CAM-112 | URL button CTA preview | Step 3/4, template has URL button | 1. Observe template buttons section 2. See URL with {{1}} placeholder | Button displays: "[Button Text] → https://example.com/?code={{1}}" URL parameter mapping shown. url_suffix field visible. | Medium |
Campaign Creation - Review & Preflight Check Step
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-027 | Review step displays campaign summary | In campaign wizard Step 4/4, all prior steps completed | 1. Arrive at Step 4/4 2. Observe summary | Summary shows: Campaign Name, WhatsApp Account, Template name, Recipient source type, recipient count, campaign mode (Standard/Paced/Autopilot), scheduled send time (if set). | High |
| CAM-028 | Preflight check - success | In campaign wizard Step 4/4, 100 recipients selected, account tier allows 1000/day | 1. Arrive at Step 4/4 (preflight runs automatically via usePreflight composable) 2. Observe PreflightBanner component result | PreflightBanner displays green checkmark. Message: "Campaign is ready to send. No issues detected." Create button enabled. | High |
| CAM-029 | Preflight check - warning - low quality rating | In campaign wizard Step 4/4, account has quality rating below threshold | 1. Arrive at Step 4/4 2. Observe PreflightBanner result | Yellow warning badge displays in banner. Message: "Account quality rating is below recommended level. Delivery may be affected." Create button still enabled (warning, not blocking). | Medium |
| CAM-030 | Preflight check - error - account tier limit exceeded | In campaign wizard Step 4/4, 500 recipients selected, account tier only allows 100/day | 1. Arrive at Step 4/4 2. Observe PreflightBanner result | Red error badge displays in banner. Message: "Your WhatsApp tier allows 100 messages/day. You selected 500 recipients. Please reduce recipients or upgrade." Create button disabled. | High |
| CAM-031 | Preflight check - error - token invalid | In campaign wizard Step 4/4, WhatsApp account token expired | 1. Arrive at Step 4/4 2. Observe PreflightBanner result | Red error badge. Message: "WhatsApp account token is invalid or expired. Please re-authenticate in Settings." Create button disabled. | High |
| CAM-032 | Schedule campaign - optional scheduling | In campaign wizard Step 4/4 | 1. Click "Schedule for later" toggle or date/time picker 2. Select future date and time 3. Click "Create & Schedule" button (via WizardFooter) | Campaign is created with status "scheduled". scheduled_at field stores the datetime. Campaign does not send until scheduled time. | High |
| CAM-033 | Schedule campaign - past datetime validation | In campaign wizard Step 4/4, scheduling enabled | 1. Attempt to select a past date/time 2. Try to create | Error displays: "Scheduled time must be in the future." Past dates are disabled in picker. | Medium |
| CAM-034 | Create campaign - save to database | In campaign wizard Step 4/4, preflight passed, all validation complete | 1. Click "Create Campaign" or "Create & Schedule" button (via WizardFooter component) 2. Wait for save | Campaign is created and saved. Success toast displays: "Campaign 'Q2 Product Launch' created successfully." Wizard closes. New campaign appears in campaigns list with status "draft" or "scheduled". | High |
| CAM-035 | Create campaign - server error handling with structured logging | In campaign wizard Step 4/4, clicking Create triggers server error (e.g., database failure) | 1. Click "Create Campaign" 2. Server returns 500 error, request context logged | Error message displays in UI: "Failed to create campaign. Please try again." Structured log entry recorded via error_adapter.log_exception() with operation="campaigns_create", request context, and full exception trace. Save button remains available for retry. Wizard does not close. | Medium |
| CAM-113 | Standard campaign CTA buttons | Step 4/4, standard mode (not scheduled) | 1. Observe WizardFooter action buttons | Buttons: "Create Campaign" (primary), "Cancel". Scheduling not shown for standard. | High |
| CAM-114 | Paced campaign CTA buttons | Step 4/4, paced mode | 1. Observe WizardFooter action buttons | Buttons: "Create & Start", "Cancel". Scheduling option available if desired. | High |
| CAM-115 | Autopilot campaign CTA buttons | Step 4/4, autopilot mode | 1. Observe WizardFooter action buttons | Buttons: "Create & Start", "Cancel". Autopilot always launches immediately (no schedule option). | High |
Campaign Detail View
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-036 | Open campaign detail view | Logged in as Agent, campaign "Q2 Launch" exists with status "draft" | 1. Navigate to /campaigns 2. Click on campaign row "Q2 Launch" | Detail modal/panel opens. Shows campaign name, status badge (draft), WhatsApp account, template, recipient count (total_recipients), campaign mode (Standard/Paced/Autopilot), and metrics (sent, delivered, read, failed). | High |
| CAM-037 | Campaign detail - draft status | Campaign exists with status "draft" | 1. Open campaign detail 2. Observe action buttons | Buttons visible: "Edit", "Delete", "Launch Now". Edit and Delete are enabled. Launch Now is enabled. | High |
| CAM-038 | Campaign detail - running status | Campaign exists with status "running" | 1. Open campaign detail | Status badge shows "running" in blue. Buttons visible: "Pause", "Cancel". No Edit button. Delete disabled. | High |
| CAM-039 | Campaign detail - paused status | Campaign exists with status "paused" | 1. Open campaign detail | Status badge shows "paused" in yellow. Buttons visible: "Resume", "Cancel", "Delete" (disabled). | Medium |
| CAM-040 | Campaign detail - completed status | Campaign exists with status "completed" (all recipients processed) | 1. Open campaign detail | Status badge shows "completed" in green. Buttons visible: "Delete", "Archive", "Duplicate". Launch/Pause/Cancel buttons hidden. Metrics show final counts. | Medium |
| CAM-041 | Campaign detail - failed status with error | Campaign exists with status "failed" (fatal error like invalid token) | 1. Open campaign detail | Status badge shows "failed" in red. Error message displayed: specific error reason (e.g., "Access token expired. Re-authenticate the WhatsApp account."). Delete button visible. | Medium |
| CAM-116 | Campaign detail - continuous (autopilot) status running | Campaign with is_continuous=true, status "running" | 1. Open campaign detail | Status badge shows "running" in blue. Progress shows active enrollment count, not 100% completion. Buttons: "Pause", "Cancel". No completion ETA. | High |
| CAM-117 | Campaign detail - paced mode with daily limit | Campaign with is_continuous=false, daily_limit=50, status "running" | 1. Open campaign detail 2. Observe daily sent counter | Displays: "Sent today: X/50" (e.g., "Sent today: 23/50"). Counter resets at midnight UTC. | High |
Campaign Recipients Tab
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-042 | Recipients list in campaign detail | Campaign "Q2 Launch" has 10 recipients with various statuses | 1. Open campaign detail 2. Click "Recipients" tab 3. Wait for list load | Recipients table displays: contact name, phone, status badge (pending/sent/delivered/read/failed), error message (if failed), sent timestamp, retry count. | High |
| CAM-043 | Recipients status filter | Campaign with 20 recipients: 10 sent, 5 delivered, 5 failed | 1. Open campaign detail, Recipients tab 2. Click status filter 3. Select "delivered" | Only 5 delivered recipients display. Other statuses hidden. Filter badge shows count. | Medium |
| CAM-044 | Recipients pagination | Campaign with 150 recipients | 1. Open campaign detail, Recipients tab 2. Scroll to bottom | Default page size 50. Pages 1-3 available. "Next" and "Previous" buttons functional. | Medium |
| CAM-045 | Recipient detail - failed with error message | Campaign with one recipient, status "failed", error_message: "Invalid phone number" | 1. Open campaign detail, Recipients tab 2. Find failed recipient row | Failed row shows error message tooltip/detail: "Invalid phone number". Retry count > 0 displayed. | Medium |
| CAM-046 | Empty recipients list (CSV with no valid rows) | Campaign created from CSV with no valid phones | 1. Open campaign detail, Recipients tab | Empty state: "No recipients found." Campaign status may be "draft" or show warning. | Low |
| CAM-125 | Recipient cancelled status - opted out | Campaign running or completed, recipient has contact with is_opted_in=false | 1. Open campaign detail, Recipients tab 2. Look for recipient row with cancelled status | Row displays with status badge "Cancelled". Hover/detail shows reason: "Contact opted out". Timestamp shows when opted-out processing occurred. | High |
| CAM-140 | Campaign recipients shown in inbox | Campaign running with recipients who received messages | 1. Open campaign detail, click "Recipients" tab 2. Select a recipient row 3. Observe inbox behavior | Recipient's message thread displays in inbox. Message has automation_metadata showing source_type="campaign", source_name=campaign name. Message status (SENT/DELIVERED/READ) matches recipient status in campaign. Contact conversation created and linked to campaign. | High |
| CAM-141 | Message thread shows campaign automation source | Campaign recipient sent via automation | 1. Open inbox, find conversation for recipient 2. View message in thread | Message displays automation badge/pill: "Campaign: Q2 Product Launch". Sender shows WhatsApp account used. Timestamp and delivery status visible. | High |
| CAM-142 | Campaign message creation with conversation link | Campaign template sent to recipient | Background: execute_campaign calls get_or_create_conversation_for_campaign() and message_service.send_template_with_sender(). Message created with automation_metadata. | Message record created in database with: wamid (WhatsApp message ID), status=SENT, automation_metadata (campaign ID/name/recipient ID), conversation_id linked, account_id linked. Conversation updated via update_conversation_on_message(). | High |
Campaign Launch & Status Transitions
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-054 | Launch campaign - draft to running (standard) | Campaign "Q2 Launch" exists with status "draft", not scheduled, preflight passed, standard mode | 1. Open campaign detail 2. Click "Launch Now" button | Confirmation modal displays: "Ready to send to 100 recipients. Continue?" 2. Click "Confirm" | Campaign status changes to "running". started_at timestamp is set. sent_count and failed_count reset to 0. Success toast: "Campaign launched." UI updates with "Pause" and "Cancel" buttons. Worker begins processing recipients via try_enqueue_campaign_execution with _job_id="campaign:{id}". Broadcast update sent via WebSocket to subscribed clients with updated campaign metrics. |
| CAM-055 | Launch scheduled campaign | Campaign exists with status "draft", scheduled_at is future date | 1. Open campaign detail | Status shows "Scheduled for [date/time]". "Launch Now" button still available to send immediately. | Medium |
| CAM-056 | Launch campaign - confirmation cancel | Campaign edit modal with Launch confirmation displayed | 1. Click "Cancel" on confirmation | Modal closes. Campaign remains in draft status. No action taken. | Medium |
| CAM-057 | Pause campaign - running to paused | Campaign with status "running", 50 messages already sent | 1. Open campaign detail 2. Click "Pause" button | Confirmation: "Pause campaign? Pending messages will not be sent." 2. Click "Confirm" | Campaign status changes to "paused". UI updates with "Resume" button. Worker stops processing further recipients after current batch. Pending recipients remain in pending state. |
| CAM-058 | Pause campaign - server error with structured logging | Campaign with status "running", clicking Pause triggers error | 1. Open campaign detail 2. Click "Pause" button 3. Confirm on dialog 4. Server returns 400/500 error | Error message displays in UI. Structured log entry recorded via error_adapter.log_exception() with operation="campaigns_pause", request, and exception. Campaign remains in "running" state. Pause button stays visible for retry. | Medium |
| CAM-059 | Resume campaign - paused to running | Campaign with status "paused" | 1. Open campaign detail 2. Click "Resume" button | Confirmation: "Resume campaign? Remaining recipients will be sent." 2. Click "Confirm" | Campaign status changes back to "running". Worker resumes processing pending recipients via try_enqueue_campaign_execution. Success toast displayed. |
| CAM-060 | Cancel campaign - running/draft/paused to cancelled | Campaign with any active status | 1. Open campaign detail 2. Click "Cancel" button | Confirmation: "Cancel campaign? This cannot be undone." 2. Click "Confirm" | Campaign status changes to "cancelled". No further messages sent. "Delete" button becomes available. UI shows final metrics (some messages may have been sent). |
| CAM-061 | Cancel campaign - server error with structured logging | Campaign with status "running", clicking Cancel triggers error | 1. Open campaign detail 2. Click "Cancel" button 3. Confirm on dialog 4. Server returns 400/500 error | Error message displays in UI. Structured log entry recorded via error_adapter.log_exception() with operation="campaigns_cancel", request, and exception. Campaign remains in current state. Cancel button stays visible for retry. | Medium |
| CAM-062 | Campaign auto-complete when all non-continuous recipients processed | Standard/paced campaign running, last recipient is processed | Background: Campaign is running with is_continuous=false. Worker finishes sending to final recipient. All recipients have status sent/delivered/failed. | Status automatically changes to "completed". started_at and completed_at both populated. Metrics show final counts. UI shows completion message: "Campaign completed. All messages sent." Broadcast update sent via WebSocket. | High |
| CAM-120 | Continuous (autopilot) campaign stays RUNNING | Autopilot campaign with is_continuous=true, running for 2 days | Background: Worker completes batch of recipients from smart segment. New recipients match segment daily. | Status remains RUNNING. Progress shows active enrollment (e.g., "1,250 contacts enrolled"), not 100% completion bar. Campaign continues until paused/cancelled. | High |
| CAM-121 | Paced campaign daily reset | Paced campaign with daily_limit=50, sent 50 yesterday | Background: New calendar day arrives. Worker calls get_remaining_daily_send_quota() which checks and resets daily_sent_reset_at. | daily_sent_count resets to 0. daily_sent_reset_at moved to next day. Remaining budget = 50 again. Worker can process next 50 messages. | High |
| CAM-122 | Paced campaign daily limit pause and resume (worker-driven) | Paced campaign with daily_limit=10, already sent 10 today | Background: Worker calls reserve_campaign_daily_send_slot() on each send. remaining_budget <= 0. | Worker breaks loop (pauses processing). Campaign stays in RUNNING state (not paused manually). No error. daily_budget_exhausted flag set. Worker resumes next day when budget resets via get_remaining_daily_send_quota(). | High |
| CAM-123 | Continuous campaign scheduled start with initial enrollment | Autopilot campaign scheduled for 2026-05-26 10:00, daily_limit=100 | Background: Scheduled time arrives. execute_campaign called. Detects is_continuous=true and scheduled_at passed. | Worker evaluates smart segment via evaluate_smart_campaign_recipients(). Enrolls initial batch (up to daily_limit). Daily counters set. Campaign status RUNNING. Subsequent worker runs add more recipients daily. Broadcast update sent on start. | High |
| CAM-138 | Worker enqueue skip - job already queued | Campaign "Test" launching, execute_campaign already in arq queue | 1. Open campaign detail 2. Click "Launch Now" 3. Wait confirmation modal 4. Click "Confirm" 5. (Job already queued from previous launch attempt or cron) | Only one arq job with _job_id="campaign:{campaign_id}" exists. Second enqueue attempt skipped silently. Log entry: "campaign_enqueue_skipped_job_active" with status="queued" or "in_progress". UI shows "Launch in progress" or similar. | High |
| CAM-139 | Worker enqueue skip - job in progress | Campaign running, cron tick fires while execute_campaign running | Background: Cron timer triggers run_smart_campaigns(). Checks for existing campaign job. | try_enqueue_campaign_execution() returns False. No duplicate job enqueued. Log entry "campaign_enqueue_skipped_job_active" with status="in_progress". Campaign continues without interruption. | High |
Campaign Live Updates via WebSocket
| ID | Test Case | Preconditions | Steps | Expected Result | Priority |
|---|---|---|---|---|---|
| CAM-144 | Campaign metrics update in real-time on campaign detail view | Logged in as Agent, campaign running, active in detail view | 1. Open campaign detail view for running campaign 2. Wait for worker to send updates (or let worker batch send) | Campaign sent_count, failed_count, and status update in real-time without page refresh. Progress bar updates as metrics change. Last updated timestamp shows current time. | High |
| CAM-145 | Campaign metrics broadcast during batch processing | Campaign running, execute_campaign worker batches recipients | Background: Worker commits after each batch. broadcast_campaign_update() called after batch commit with should_broadcast_progress() check. Worker increments sent/failed counters. | Broadcast message sent to organization's WebSocket channel with campaign JSON. Listening clients (detail views, list views) receive and update metrics. sent_count and failed_count reflect current batch progress. Broadcast happens at meaningful intervals (not every single recipient). | High |