267 lines
8.9 KiB
Ruby
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)
|