"""Unit tests for participant utility functions.""" from datetime import UTC, datetime from src.utils.participant import ( can_update_profile, can_withdraw, get_active_participants, is_withdrawn, ) def test_get_active_participants_excludes_withdrawn( exchange_factory, participant_factory ): """Test that get_active_participants excludes withdrawn participants.""" exchange = exchange_factory() # Create 2 active, 1 withdrawn active1 = participant_factory(exchange=exchange, name="Alice") active2 = participant_factory(exchange=exchange, name="Bob") withdrawn = participant_factory( exchange=exchange, name="Charlie", withdrawn_at=datetime.now(UTC) ) participants = get_active_participants(exchange.id) assert len(participants) == 2 assert active1 in participants assert active2 in participants assert withdrawn not in participants def test_get_active_participants_ordered_by_name(exchange_factory, participant_factory): """Test that participants are ordered alphabetically.""" exchange = exchange_factory() participant_factory(exchange=exchange, name="Zoe") participant_factory(exchange=exchange, name="Alice") participant_factory(exchange=exchange, name="Bob") participants = get_active_participants(exchange.id) assert len(participants) == 3 assert participants[0].name == "Alice" assert participants[1].name == "Bob" assert participants[2].name == "Zoe" def test_get_active_participants_empty_when_all_withdrawn( exchange_factory, participant_factory ): """Test that empty list returned when all participants withdrawn.""" exchange = exchange_factory() participant_factory(exchange=exchange, withdrawn_at=datetime.now(UTC)) participant_factory(exchange=exchange, withdrawn_at=datetime.now(UTC)) participants = get_active_participants(exchange.id) assert len(participants) == 0 def test_get_active_participants_different_exchanges( exchange_factory, participant_factory ): """Test that participants are filtered by exchange_id.""" exchange1 = exchange_factory() exchange2 = exchange_factory() participant_factory(exchange=exchange1, name="Alice") participant_factory(exchange=exchange2, name="Bob") participants = get_active_participants(exchange1.id) assert len(participants) == 1 assert participants[0].name == "Alice" def test_is_withdrawn_true(participant_factory): """Test is_withdrawn returns True for withdrawn participant.""" participant = participant_factory(withdrawn_at=datetime.now(UTC)) assert is_withdrawn(participant) is True def test_is_withdrawn_false(participant_factory): """Test is_withdrawn returns False for active participant.""" participant = participant_factory() assert is_withdrawn(participant) is False def test_can_update_profile_draft_state(participant_factory, exchange_factory): """Profile updates allowed in draft state.""" exchange = exchange_factory(state="draft") participant = participant_factory(exchange=exchange) assert can_update_profile(participant) is True def test_can_update_profile_registration_open(participant_factory, exchange_factory): """Profile updates allowed when registration open.""" exchange = exchange_factory(state="registration_open") participant = participant_factory(exchange=exchange) assert can_update_profile(participant) is True def test_can_update_profile_registration_closed(participant_factory, exchange_factory): """Profile updates allowed when registration closed.""" exchange = exchange_factory(state="registration_closed") participant = participant_factory(exchange=exchange) assert can_update_profile(participant) is True def test_can_update_profile_matched_state(participant_factory, exchange_factory): """Profile updates blocked after matching.""" exchange = exchange_factory(state="matched") participant = participant_factory(exchange=exchange) assert can_update_profile(participant) is False def test_can_update_profile_completed_state(participant_factory, exchange_factory): """Profile updates blocked when completed.""" exchange = exchange_factory(state="completed") participant = participant_factory(exchange=exchange) assert can_update_profile(participant) is False def test_can_withdraw_draft_state(participant_factory, exchange_factory): """Withdrawal allowed in draft state.""" exchange = exchange_factory(state="draft") participant = participant_factory(exchange=exchange) assert can_withdraw(participant) is True def test_can_withdraw_registration_open(participant_factory, exchange_factory): """Withdrawal allowed when registration open.""" exchange = exchange_factory(state="registration_open") participant = participant_factory(exchange=exchange) assert can_withdraw(participant) is True def test_can_withdraw_registration_closed(participant_factory, exchange_factory): """Withdrawal blocked when registration closed.""" exchange = exchange_factory(state="registration_closed") participant = participant_factory(exchange=exchange) assert can_withdraw(participant) is False def test_can_withdraw_matched_state(participant_factory, exchange_factory): """Withdrawal blocked after matching.""" exchange = exchange_factory(state="matched") participant = participant_factory(exchange=exchange) assert can_withdraw(participant) is False def test_can_withdraw_already_withdrawn(participant_factory): """Withdrawal blocked if already withdrawn.""" participant = participant_factory(withdrawn_at=datetime.now(UTC)) assert can_withdraw(participant) is False