Automation End-to-End Testing Guide
Automation End-to-End Testing Guide
Prerequisites
Info
Fresh authentication token (expires in ~1 hour). Try hardcoding variable value in message - If that works, interpolation is broken - If that doesn't work, step execution is broken
Warning
Fresh authentication token (expires in ~1 hour). Try hardcoding variable value in message - If that works, interpolation is broken - If that doesn't work, step execution is broken
Success
Fresh authentication token (expires in ~1 hour). Try hardcoding variable value in message - If that works, interpolation is broken - If that doesn't work, step execution is broken
Error
Fresh authentication token (expires in ~1 hour). Try hardcoding variable value in message - If that works, interpolation is broken - If that doesn't work, step execution is broken
<strong>Required:</strong>
- Fresh authentication token (expires in ~1 hour)
- Workspace ID: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">UIDRinD8Ef8UK1pxvdlv</code>
- Automation ID: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">xjDJ2Haamnapqf9V7Y4h</code>
- Test widget key (inbox/channel ID the automation is attached to)
- Localhost backend running on port 3030
- Browser dev console open to monitor real-time messages
Phase 1: Pre-Test Verification
1.1 Verify Automation Structure
<strong>Verify these fields are present:</strong>
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">trigger</code> — the entry point (e.g., conversation<em>created, message</em>received, etc.)
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">triggerNextStepId</code> — points to first step after trigger
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">steps</code> — array of all step objects
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">channels</code> — array of channels trigger applies to
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">frequency</code> — every<em>time / once</em>per<em>contact / once</em>per_conversation
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">schedule</code> — { type: 'any<em>time' | 'office</em>hours' | 'custom', ... }
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">audienceFilters</code> — filtering rules { logic: 'AND'|'OR', groups: [...] }
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">goal</code> — success metric { enabled: bool, type, window }
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">status</code> — must be 'live' to trigger
Phase 2: Trigger Testing
Scenario 2.1: Initial Trigger Activation
<strong>Setup:</strong>
- Open test page with widget (or create test contact widget at <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">localhost:3000</code>)
- Widget loads with test key
- Watch browser console for Pusher messages
<strong>Action:</strong>
- Send first message from widget as <strong>anonymous visitor</strong>
- Message: "Hello" (simple starter)
<strong>Expected Flow:</strong>
- ✅ Backend creates new conversation
- ✅ Automation <strong>trigger matches</strong> (conversation_created fires)
- ✅ Backend creates enrollment record
- ✅ First step after trigger begins executing
- ✅ Pusher event fires: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflowQuestion</code> or <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflowChoices</code> or <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">message:new</code>
- ✅ Widget receives event and updates UI
<strong>What to Watch:</strong>
- Browser console: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">Pusher <private-conversation-ID> message:new</code>
- Browser console: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">Pusher <private-conversation-ID> workflowQuestion</code> (if ask_question)
- Browser console: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">Pusher <private-conversation-ID> workflowChoices</code> (if choices)
- Backend logs: no errors during step execution
<strong>Common Bugs:</strong>
- ❌ No Pusher event fired → step executor failed
- ❌ Event fired but widget doesn't update → subscription issue
- ❌ Trigger doesn't fire at all → status not 'live' or frequency/schedule blocked
Scenario 2.2: Frequency Control
<strong>Test:</strong> Ensure frequency setting prevents duplicate automations
<strong>Setup:</strong>
- Automation frequency = "once<em>per</em>contact"
<strong>Action:</strong>
- Send message #1: "Hi"
- ✅ Automation should trigger
- Send message #2: "Hi again"
- ❌ Automation should NOT trigger again (frequency blocks it)
<strong>Expected:</strong>
- First message: automation runs
- Subsequent messages from same contact: automation skipped
<strong>Verify in Firestore:</strong>
- Check <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">enrollments</code> collection
- Contact should have only 1 enrollment for this automation
- Status: 'completed' or 'in_progress'
Scenario 2.3: Schedule Control
<strong>Setup:</strong>
- Automation schedule = "office_hours" (9am-5pm)
- Test outside office hours
<strong>Action:</strong>
- Send message at 6:00 PM
- ❌ Automation should NOT trigger (schedule blocks it)
<strong>Verify:</strong>
- Check backend logs for schedule evaluation
- Message arrives but automation enrollment not created
Phase 3: Step Execution Testing
Scenario 3.1: ask_question Step
<strong>Setup:</strong>
- First step after trigger = <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">ask_question</code>
- Question text: "What is your name?"
- Variable name: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">user_name</code>
<strong>Action:</strong>
- Send message: "Hello"
- Automation triggers
- Bot asks: "What is your name?"
- <strong>WAIT</strong> — automation pauses
<strong>Expected:</strong>
- ✅ Message appears in widget conversation
- ✅ Conversation conversation has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflow.awaitingQuestion = true</code>
- ✅ Conversation has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflow.questionVariableName = 'user_name'</code>
- ✅ Widget shows <strong>input mode</strong> or question UI
<strong>What Breaks:</strong>
- ❌ Question doesn't appear → step didn't execute
- ❌ Question appears but widget crashes → UI doesn't handle event
- ❌ Response gets lost → resumeQuestion handler failed
Scenario 3.2: Resuming From ask_question
<strong>Setup:</strong> (continuing from 3.1)
<strong>Action:</strong>
- User types response: "John"
- Submit via widget
<strong>Expected Flow:</strong>
- ✅ Widget sends POST to <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">/api/v1/automations/question/answer</code>
<code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em"></code>`json<br> {<br> "conversationId": "...",<br> "answer": "John",<br> "variableName": "user_name",<br> "enrollmentId": "..."<br> }<br> <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em"></code>`
- ✅ Backend resumes automation from pause point
- ✅ Variable <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">user_name</code> = "John" available to next steps
- ✅ "John" response is saved to conversation messages
- ✅ Next step executes
<strong>What to Monitor:</strong>
- ✅ User's response appears in conversation as message
- ✅ Check Firestore <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">conversations.workflow.variables.user_name</code> = "John"
- ✅ Check <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">enrollments.variables.user_name</code> = "John"
<strong>Common Issues:</strong>
- ❌ Response doesn't appear in conversation → message creation failed
- ❌ Variable not stored → resumeQuestion didn't save it properly
- ❌ Automation doesn't continue → nextStepId not set
Scenario 3.3: choices Step
<strong>Setup:</strong>
- After ask_question, choices step appears
- Prompt: "Which service do you need?"
- Choices: ["Billing", "Technical Support", "Sales"]
- Branches: 3 branches (one per choice)
<strong>Action:</strong>
- Bot sends: "Which service do you need?"
- Widget shows <strong>choice buttons</strong>
- User clicks "Billing"
<strong>Expected:</strong>
- ✅ Prompt appears as bot message
- ✅ Conversation has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflow.awaitingChoice = true</code>
- ✅ Conversation has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflow.currentChoices = ["Billing", "Technical Support", "Sales"]</code>
- ✅ Conversation has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflow.choiceConnections</code> = [nextStepId1, nextStepId2, nextStepId3]
<strong>What to Monitor:</strong>
- Browser console: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">Pusher workflowChoices</code> event
- Widget displays choice buttons
- Each button is clickable
Scenario 3.4: Resuming From choices
<strong>Action:</strong>
- User clicks "Billing"
<strong>Expected Flow:</strong>
- ✅ Widget POST to <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">/api/v1/automations/choice/select</code>
- ✅ Automation branches to choice[0].nextStepId
- ✅ "Billing" selection appears in conversation
- ✅ Next step in Billing branch executes
<strong>Verify in Firestore:</strong>
- Choice selection saved to messages (either as user message or bot message)
- Variable <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">last_choice</code> = "Billing"
- Enrollment continues on correct branch
Phase 4: Action Steps Testing
Scenario 4.1: send_message Action
<strong>Setup:</strong>
- Step after choices: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">send_message</code>
- Content: "You selected {{last_choice}}. We'll connect you soon!"
<strong>Action:</strong>
- Trigger automation through full flow
- Select a choice
- Wait for message
<strong>Expected:</strong>
- ✅ Message appears in conversation
- ✅ Content interpolates variable: "You selected Billing. We'll connect you soon!"
- ✅ Message has <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">senderType = 'bot'</code>
<strong>Common Issues:</strong>
- ❌ Variable not interpolated → context.variables not passed
- ❌ Message doesn't appear → step executor failed
Scenario 4.2: assign Step
<strong>Setup:</strong>
- After choices: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">assign</code> step
- Assign to: "Billing" inbox (from choices)
- Message: "Routing to {{last_choice}} team..."
<strong>Action:</strong>
- Trigger automation to assignment step
- Select "Billing"
<strong>Expected:</strong>
- ✅ Conversation routed to Billing inbox
- ✅ <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">conversation.inboxId</code> = billingInboxId
- ✅ Notification message appears: "Routing to Billing team..."
- ✅ Agent sees conversation in Billing inbox
<strong>Verify:</strong>
- Check Firestore conversation.inboxId
- Check agent inbox (might need to refresh)
Scenario 4.3: route<em>to</em>inbox Step
<strong>Setup:</strong>
- Step: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">route<em>to</em>inbox</code>
- Config: map choices to specific inboxes
- "Billing" → Billing Inbox<br> - "Technical Support" → Support Inbox<br> - "Sales" → Sales Inbox
<strong>Action:</strong>
- Full automation flow, select choice
- Step routes to mapped inbox
<strong>Expected:</strong>
- ✅ Conversation moves to selected inbox
- ✅ Assignment message appears
- ✅ Agent can see conversation
Scenario 4.4: Condition Branching
<strong>Setup:</strong>
- After choices, condition step
- Condition: "If last_choice == 'Technical Support', then..."
- True branch: technical support flow
- False branch: sales flow
<strong>Action:</strong>
- Choose "Technical Support"
- Follow automation
<strong>Expected:</strong>
- ✅ Condition evaluates to true
- ✅ Automation follows <strong>true branch</strong>
- ✅ Technical support actions execute
<strong>Test All Branches:</strong>
- ✅ last_choice = "Billing" → false branch
- ✅ last_choice = "Sales" → false branch
- ✅ last_choice = "Technical Support" → true branch
Phase 5: End-to-End Scenario Testing
Scenario 5.1: Complete "Route to Support" Flow
<strong>Full Path:</strong>
<strong>Manual Test Steps:</strong>
- [ ] Load widget
- [ ] Send: "Hi"
- Verify: Bot asks "What is your name?"
- [ ] Send: "John"
- Verify: "Thanks, John!" appears<br> - Verify: Choice buttons appear
- [ ] Click: "Technical Support"
- Verify: "Connecting to support team..." appears<br> - Verify: Conversation moves to Support inbox
- [ ] Check inbox: Conversation should appear in Support
<strong>Monitor for Bugs:</strong>
- [ ] Variables not available in interpolation
- [ ] Messages in wrong order
- [ ] Condition branching wrong
- [ ] Inbox assignment fails
- [ ] Pusher events delayed
Phase 6: Error Scenarios
Scenario 6.1: Missing Required Data
<strong>Setup:</strong>
- Automation with variables in actions
<strong>Action:</strong>
- Skip ask<em>question step (jump to send</em>message using variable)
- Variable not defined
<strong>Expected:</strong>
- ❌ Message appears with empty variable: "You selected ." (graceful degradation)
- OR ✅ Error logged, message not sent
<strong>What to Monitor:</strong>
- Check <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">enrollments.variables</code> object
- Verify interpolation handles missing variables
Scenario 6.2: Inbox Not Found
<strong>Setup:</strong>
- assign step references non-existent inbox ID
<strong>Action:</strong>
- Trigger automation to assignment
<strong>Expected:</strong>
- ❌ Error logged in backend
- ❌ Conversation NOT assigned
- ❌ Automation should not crash
<strong>Verify:</strong>
- Check backend logs for error
- Check conversation status (should remain open, not assigned)
Scenario 6.3: Agent Offline / Unavailable
<strong>Setup:</strong>
- assign step to specific agent
- Agent is offline
<strong>Action:</strong>
- Trigger automation to assignment
<strong>Expected:</strong>
- ✅ Conversation assigned anyway (no availability check)
- OR ⚠️ Queue conversation for next available agent (if implemented)
Phase 7: Variable & Context Testing
Scenario 7.1: Contact Attributes in Messages
<strong>Setup:</strong>
- Contact created with phone, company, language
- Automation message: "Hello {{contact.firstName}}, from {{contact.company}}"
<strong>Action:</strong>
- Send message as logged-in contact
<strong>Expected:</strong>
- ✅ Message: "Hello John, from Acme Inc"
Scenario 7.2: Conversation Attributes in Conditions
<strong>Setup:</strong>
- Condition: if conversation.language == "fr"
- Contact set language to French
<strong>Action:</strong>
- Trigger automation
<strong>Expected:</strong>
- ✅ Condition evaluates correctly based on contact.language
Phase 8: Performance & Real-Time
Scenario 8.1: Message Latency
<strong>Setup:</strong>
- Automation with multiple steps
- Browser dev tools Performance tab open
<strong>Action:</strong>
- Send message to trigger
- Measure time for response to appear
<strong>Expected:</strong>
- Bot response appears within 2-3 seconds
- No janky rendering or lag
Scenario 8.2: Concurrent Conversations
<strong>Setup:</strong>
- Multiple browser tabs / incognito windows
- Each with different visitor identities
<strong>Action:</strong>
- Send message in each tab
- Different automations should run independently
<strong>Expected:</strong>
- ✅ Each conversation enrolls in automation separately
- ✅ Variables don't leak between conversations
- ✅ All receive responses correctly
Debugging Checklist
If automation doesn't trigger:
If step doesn't execute:
- Check Firestore <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">enrollments.{enrollmentId}</code>
- Look at <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">currentStepId</code> — is it correct?<br> - Look at <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">variables</code> — did previous steps run?
- Check backend logs
- Search for <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">[AutomationEngine]</code><br> - Look for step executor errors
- Check Pusher events
- Browser console: <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">Pusher <channel> <event></code><br> - Should see <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">message:new</code>, <code style="font-family:ui-monospace,monospace;background:#f1f5f9;color:#dc2626;padding:0.1em 0.35em;border-radius:3px;font-size:0.875em">workflowQuestion</code>, etc.
If variable not available:
- Check enrollment.variables object
- Should contain variableName = value
- Check context passed to step
- Backend logs should show context.variables
- Test interpolation
- Try hardcoding variable value in message<br> - If that works, interpolation is broken<br> - If that doesn't work, step execution is broken
Success Criteria
✅ <strong>Automation is working when:</strong>
- [ ] Trigger fires correctly
- [ ] First step executes (question/choice/action)
- [ ] ask_question pauses and resumes correctly
- [ ] Choices branch correctly
- [ ] Variables are saved and available
- [ ] Assignments route to correct inboxes
- [ ] Messages appear in conversation
- [ ] Multiple conversations don't interfere
- [ ] No console errors
- [ ] Pusher events arrive in real-time
❌ <strong>Bugs to report:</strong>
- Variables not interpolating
- Steps not executing in order
- Branching takes wrong path
- Assignments go to wrong inbox
- Messages appear out of order
- Automation stops mid-flow
- Variables disappear
- Slow responses (>5s)
Next Steps
- <strong>Get fresh token</strong> — current one expired
- <strong>Run Phase 2</strong> — verify automation structure is correct
- <strong>Run Phase 3</strong> — test basic steps (ask_question, choices)
- <strong>Run Phase 5</strong> — full end-to-end scenario
- <strong>Document bugs</strong> found and their exact steps to reproduce
- <strong>Create Firestore queries</strong> to verify enrollment state
Did this answer your question?