Files
chatwoot/script/assignment_v2/test_edge_cases.rb
T

267 lines
8.9 KiB
Ruby

# frozen_string_literal: true
# Test: Edge Cases and Error Scenarios
# Run with: bundle exec rails runner script/assignment_v2/test_edge_cases.rb
#
# Tests:
# - No agents online: assignment returns 0, conversations remain unassigned
# - No conversations to assign: assignment completes without error
# - Policy disabled: assignment still works (policy just not enforced)
# - Auto-assignment disabled on inbox: assignment returns 0
# - All agents at rate limit: no assignments happen
# - Resolved/snoozed conversations: not assigned (only open+unassigned)
#
# Key Implementation Details:
# - AssignmentService.perform_bulk_assignment returns 0 if no eligible conversations
# - inbox.auto_assignment_v2_enabled? checks inbox.enable_auto_assignment flag
# - Only conversations with status='open' and assignee_id=nil are eligible
# - Policy.enabled flag doesn't block assignment, just affects policy behavior
# - When no agents available, assignment gracefully returns 0 (no errors)
require_relative 'test_helpers'
class TestEdgeCases
include AssignmentV2TestHelpers
def run
section('TEST: Edge Cases and Error Scenarios')
account = get_test_account
inbox = nil
begin
# Test 1: No agents online
section('Test 1: No Agents Online')
inbox = create_test_inbox(account, name: 'Edge Case Test Inbox')
policy = create_test_policy(account, name: 'Edge Case Policy')
link_policy_to_inbox(inbox, policy)
# Create agent but keep them offline
agent_offline = create_test_agent(account, inbox, name: 'Agent Offline', online: false)
info("Created offline agent: #{agent_offline.name}")
# Create 3 conversations
create_bulk_conversations(inbox, count: 3)
# Run assignment - should assign 0 (no online agents)
assigned_count = run_assignment(inbox)
log('Verifying no agents online...', color: :blue)
# Should assign 0
none_assigned = assert_equal(
assigned_count,
0,
'No conversations assigned (no online agents)'
)
# All conversations should remain unassigned
still_unassigned = assert_equal(
inbox.conversations.unassigned.count,
3,
'All 3 conversations remain unassigned'
)
test1_ok = none_assigned && still_unassigned
# Test 2: No conversations to assign
section('Test 2: No Conversations to Assign')
# Bring agent online
OnlineStatusTracker.update_presence(account.id, 'User', agent_offline.id)
OnlineStatusTracker.set_status(account.id, agent_offline.id, 'online')
info("Brought #{agent_offline.name} online")
# Assign all existing conversations manually
inbox.conversations.unassigned.each { |conv| conv.update!(assignee: agent_offline) }
info('Manually assigned all existing conversations')
# Run assignment with no unassigned conversations
assigned_count_2 = run_assignment(inbox)
log('Verifying no conversations to assign...', color: :blue)
# Should assign 0 (nothing to assign)
none_to_assign = assert_equal(
assigned_count_2,
0,
'No conversations assigned (none available)'
)
# No unassigned conversations
no_unassigned = assert_equal(
inbox.conversations.unassigned.count,
0,
'No unassigned conversations'
)
test2_ok = none_to_assign && no_unassigned
# Test 3: Policy disabled (note: inbox.enable_auto_assignment not yet implemented)
section('Test 3: Policy Disabled')
# Create new conversations
create_bulk_conversations(inbox, count: 3)
# Disable policy
policy.update!(enabled: false)
info('Disabled policy')
# Run assignment - policy disabled doesn't block assignment in current implementation
# Policy.enabled is intended for future use but doesn't currently affect assignment
run_assignment(inbox)
log('Verifying policy disabled (no effect currently)...', color: :blue)
# NOTE: Policy.enabled doesn't actually block assignment yet, so this will assign
# We're testing that assignment doesn't crash when policy is disabled
policy_disabled_ok = assert(
true, # Just verify no crash
'Assignment runs without error when policy disabled',
'Assignment crashed when policy disabled'
)
# Re-enable policy for next tests
policy.update!(enabled: true)
test3_ok = policy_disabled_ok
# Test 4: All agents at rate limit
section('Test 4: All Agents at Rate Limit')
# Clear all conversations and start fresh
inbox.conversations.destroy_all
info('Cleared all conversations for rate limit test')
# Update existing policy with very low rate limit
policy.update!(
fair_distribution_limit: 1,
fair_distribution_window: 3600
)
# Re-link to sync config to inbox
link_policy_to_inbox(inbox, policy)
info('Updated policy: rate limit = 1 conversation per agent')
# Create 3 new conversations
create_bulk_conversations(inbox, count: 3)
# Run assignment once - should assign 1 (hitting the limit)
assigned_count_first = run_assignment(inbox)
info("First assignment: assigned #{assigned_count_first} conversation(s), agent now at limit")
# Verify first assignment worked
first_assign_ok = assert_equal(
assigned_count_first,
1,
'First assignment assigned 1 conversation (limit reached)'
)
# Now agent is at limit (1/1), 2 conversations remain unassigned
# Run assignment again - should assign 0 (agent at limit)
assigned_count_4 = run_assignment(inbox)
log('Verifying all agents at limit...', color: :blue)
# Should assign 0
at_limit_ok = assert_equal(
assigned_count_4,
0,
'No conversations assigned (all agents at rate limit)'
)
# 2 conversations remain unassigned
unassigned_at_limit = assert_equal(
inbox.conversations.unassigned.count,
2,
'2 conversations remain unassigned'
)
test4_ok = first_assign_ok && at_limit_ok && unassigned_at_limit
# Test 5: Only resolved/snoozed conversations (not eligible)
section('Test 5: Only Resolved/Snoozed Conversations')
# Create new inbox to start fresh
inbox2 = create_test_inbox(account, name: 'Status Test Inbox')
policy2 = create_test_policy(account, name: 'Status Test Policy')
link_policy_to_inbox(inbox2, policy2)
create_test_agent(account, inbox2, name: 'Agent Status Test', online: true)
# Create conversations with different statuses
conv_resolved = create_test_conversation(inbox2, contact_name: 'Resolved Customer', status: 'resolved')
conv_snoozed = create_test_conversation(inbox2, contact_name: 'Snoozed Customer', status: 'snoozed')
conv_pending = create_test_conversation(inbox2, contact_name: 'Pending Customer', status: 'pending')
info('Created conversations with statuses: resolved, snoozed, pending')
# Run assignment - should assign 0 (no open conversations)
assigned_count_5 = run_assignment(inbox2)
log('Verifying non-open conversations not assigned...', color: :blue)
# Should assign 0
status_ok = assert_equal(
assigned_count_5,
0,
'No conversations assigned (all are resolved/snoozed/pending)'
)
# All conversations remain unassigned
conv_resolved.reload
conv_snoozed.reload
conv_pending.reload
none_assigned_5 = assert(
conv_resolved.assignee_id.nil? &&
conv_snoozed.assignee_id.nil? &&
conv_pending.assignee_id.nil?,
'All non-open conversations remain unassigned',
'Some non-open conversations were assigned'
)
# Create 1 open conversation - should be assigned
conv_open = create_test_conversation(inbox2, contact_name: 'Open Customer', status: 'open')
assigned_count_6 = run_assignment(inbox2)
# Should assign 1
open_assigned = assert_equal(
assigned_count_6,
1,
'Open conversation assigned'
)
conv_open.reload
open_has_assignee = assert(
conv_open.assignee_id.present?,
'Open conversation has assignee',
'Open conversation not assigned'
)
test5_ok = status_ok && none_assigned_5 && open_assigned && open_has_assignee
# Cleanup inbox2
cleanup_test_data(account, inbox: inbox2)
# 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(TestEdgeCases.new.run ? 0 : 1)