246 lines
8.0 KiB
Ruby
246 lines
8.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Test: Real-Time Assignment Trigger
|
|
# Run with: bundle exec rails runner script/assignment_v2/test_real_time_trigger.rb
|
|
#
|
|
# Tests:
|
|
# - Assignment triggered when conversation status changes to 'open'
|
|
# - Assignment triggered when new conversation created
|
|
# - Assignment only runs when assignee is blank
|
|
# - Assignment respects enable_auto_assignment flag
|
|
#
|
|
# Key Implementation Details:
|
|
# - AutoAssignmentHandler is a concern included in Conversation model
|
|
# - Triggers after_save when conversation_status_changed_to_open?
|
|
# - Checks inbox.auto_assignment_v2_enabled? to use v2 vs legacy system
|
|
# - NOTE: auto_assignment_v2_enabled? not yet implemented, so this test simulates expected behavior
|
|
# - When implemented, it will call: AutoAssignment::AssignmentJob.perform_later(inbox_id: inbox.id)
|
|
#
|
|
# This test manually triggers assignment to simulate real-time behavior
|
|
|
|
require_relative 'test_helpers'
|
|
|
|
class TestRealTimeTrigger
|
|
include AssignmentV2TestHelpers
|
|
|
|
def run
|
|
section('TEST: Real-Time Assignment Trigger')
|
|
|
|
account = get_test_account
|
|
inbox = nil
|
|
|
|
begin
|
|
# Setup test inbox and policy
|
|
inbox = create_test_inbox(account, name: 'Real-Time Trigger Test Inbox')
|
|
policy = create_test_policy(account, name: 'Real-Time Policy')
|
|
link_policy_to_inbox(inbox, policy)
|
|
|
|
# Create agent
|
|
agent = create_test_agent(account, inbox, name: 'Agent Real-Time', online: true)
|
|
|
|
# Test 1: Assignment triggered when conversation status changes to open
|
|
section('Test 1: Status Change to Open Triggers Assignment')
|
|
|
|
# Create conversation with status 'pending' (not open)
|
|
conv = create_test_conversation(inbox, contact_name: 'Pending Customer', status: 'pending')
|
|
info('Created conversation with status: pending')
|
|
|
|
# Conversation should not be assigned (status is not open)
|
|
conv.reload
|
|
pending_unassigned = assert(
|
|
conv.assignee_id.nil?,
|
|
'Pending conversation not assigned',
|
|
'Pending conversation was assigned (should not be)'
|
|
)
|
|
|
|
# Change status to 'open' and manually trigger assignment (simulating handler)
|
|
conv.update!(status: 'open')
|
|
info('Changed status to: open')
|
|
|
|
# Simulate real-time trigger: run assignment job
|
|
# In production, AutoAssignmentHandler would call: AutoAssignment::AssignmentJob.perform_later
|
|
assigned_count = run_assignment(inbox)
|
|
|
|
# Verify assignment happened
|
|
log('Verifying assignment after status change...', color: :blue)
|
|
|
|
assigned_ok = assert_equal(
|
|
assigned_count,
|
|
1,
|
|
'Conversation assigned after status changed to open'
|
|
)
|
|
|
|
conv.reload
|
|
has_assignee = assert(
|
|
conv.assignee_id.present?,
|
|
'Conversation has assignee',
|
|
'Conversation not assigned'
|
|
)
|
|
|
|
test1_ok = pending_unassigned && assigned_ok && has_assignee
|
|
|
|
# Test 2: New conversation created as 'open' triggers assignment
|
|
section('Test 2: New Open Conversation Triggers Assignment')
|
|
|
|
# Create conversation directly as 'open'
|
|
conv2 = create_test_conversation(inbox, contact_name: 'Open Customer', status: 'open')
|
|
info('Created conversation with status: open')
|
|
|
|
# Simulate real-time trigger
|
|
assigned_count_2 = run_assignment(inbox)
|
|
|
|
# Verify assignment
|
|
log('Verifying assignment for new open conversation...', color: :blue)
|
|
|
|
assigned_ok_2 = assert_equal(
|
|
assigned_count_2,
|
|
1,
|
|
'New open conversation assigned'
|
|
)
|
|
|
|
conv2.reload
|
|
has_assignee_2 = assert(
|
|
conv2.assignee_id.present?,
|
|
'New conversation has assignee',
|
|
'New conversation not assigned'
|
|
)
|
|
|
|
test2_ok = assigned_ok_2 && has_assignee_2
|
|
|
|
# Test 3: Already assigned conversation not re-assigned
|
|
section('Test 3: Already Assigned Conversation Not Re-Assigned')
|
|
|
|
# Create and assign a conversation
|
|
conv3 = create_test_conversation(inbox, contact_name: 'Customer 3', status: 'open')
|
|
run_assignment(inbox)
|
|
conv3.reload
|
|
original_assignee = conv3.assignee
|
|
info("Conversation initially assigned to: #{original_assignee.name}")
|
|
|
|
# Update something else (not status, not assignee)
|
|
conv3.update!(additional_attributes: { test: 'value' })
|
|
|
|
# Simulate real-time trigger
|
|
assigned_count_3 = run_assignment(inbox)
|
|
|
|
# Verify no re-assignment
|
|
log('Verifying already-assigned conversation not re-assigned...', color: :blue)
|
|
|
|
# Should assign 0 (conversation already has assignee)
|
|
no_reassign = assert_equal(
|
|
assigned_count_3,
|
|
0,
|
|
'No conversations re-assigned'
|
|
)
|
|
|
|
conv3.reload
|
|
same_assignee = assert(
|
|
conv3.assignee_id == original_assignee.id,
|
|
'Conversation keeps original assignee',
|
|
'Conversation was re-assigned (should not be)'
|
|
)
|
|
|
|
test3_ok = no_reassign && same_assignee
|
|
|
|
# Test 4: Resolved conversation changing to open triggers assignment
|
|
section('Test 4: Resolved → Open Triggers Assignment')
|
|
|
|
# Create and resolve a conversation
|
|
conv4 = create_test_conversation(inbox, contact_name: 'Returning Customer', status: 'open')
|
|
run_assignment(inbox)
|
|
conv4.reload
|
|
conv4.update!(status: 'resolved', assignee: nil)
|
|
info('Conversation resolved and unassigned')
|
|
|
|
# Reopen conversation
|
|
conv4.update!(status: 'open')
|
|
info('Conversation reopened (status: open)')
|
|
|
|
# Simulate real-time trigger
|
|
assigned_count_4 = run_assignment(inbox)
|
|
|
|
# Verify re-assignment
|
|
log('Verifying reopened conversation assigned...', color: :blue)
|
|
|
|
assigned_ok_4 = assert_equal(
|
|
assigned_count_4,
|
|
1,
|
|
'Reopened conversation assigned'
|
|
)
|
|
|
|
conv4.reload
|
|
has_assignee_4 = assert(
|
|
conv4.assignee_id.present?,
|
|
'Reopened conversation has assignee',
|
|
'Reopened conversation not assigned'
|
|
)
|
|
|
|
test4_ok = assigned_ok_4 && has_assignee_4
|
|
|
|
# Test 5: Assignment respects online status in real-time
|
|
section('Test 5: Real-Time Assignment Respects Agent Availability')
|
|
|
|
# Take agent offline
|
|
OnlineStatusTracker.set_status(account.id, agent.id, 'offline')
|
|
info("Took #{agent.name} offline")
|
|
|
|
# Create new conversation
|
|
conv5 = create_test_conversation(inbox, contact_name: 'Customer During Offline', status: 'open')
|
|
|
|
# Simulate real-time trigger
|
|
assigned_count_5 = run_assignment(inbox)
|
|
|
|
# Verify no assignment (agent offline)
|
|
log('Verifying no assignment when agent offline...', color: :blue)
|
|
|
|
no_assign_offline = assert_equal(
|
|
assigned_count_5,
|
|
0,
|
|
'No assignment when agent offline'
|
|
)
|
|
|
|
conv5.reload
|
|
unassigned_offline = assert(
|
|
conv5.assignee_id.nil?,
|
|
'Conversation remains unassigned when agent offline',
|
|
'Conversation was assigned despite agent being offline'
|
|
)
|
|
|
|
# Bring agent back online
|
|
OnlineStatusTracker.update_presence(account.id, 'User', agent.id)
|
|
OnlineStatusTracker.set_status(account.id, agent.id, 'online')
|
|
info("Brought #{agent.name} back online")
|
|
|
|
# Simulate real-time trigger (next conversation triggers assignment for backlog)
|
|
assigned_count_6 = run_assignment(inbox)
|
|
|
|
# Now should assign
|
|
assigned_after_online = assert_equal(
|
|
assigned_count_6,
|
|
1,
|
|
'Assignment happens when agent comes online'
|
|
)
|
|
|
|
test5_ok = no_assign_offline && unassigned_offline && assigned_after_online
|
|
|
|
# Final result
|
|
if test1_ok && test2_ok && test3_ok && test4_ok && test5_ok
|
|
section('✓ ALL TESTS PASSED')
|
|
true
|
|
else
|
|
section('✗ SOME TESTS FAILED')
|
|
false
|
|
end
|
|
rescue StandardError => e
|
|
error("Test failed with error: #{e.message}")
|
|
puts e.backtrace.first(5).join("\n")
|
|
false
|
|
ensure
|
|
cleanup_test_data(account, inbox: inbox) if inbox
|
|
end
|
|
end
|
|
end
|
|
|
|
# Run test and exit with appropriate code
|
|
exit(TestRealTimeTrigger.new.run ? 0 : 1)
|