import pytest from services.card_service import Card, CardService class FakeSession: pass @pytest.mark.asyncio async def test_activate_card_keeps_existing_device_cards(monkeypatch): service = CardService() existing = Card( card_id=1, card_uuid="CARD_A", device_id="TalkingQ_device001", status=1, ) saved_cards = [] session = FakeSession() async def fake_init_database(): return None async def fake_get_card_by_uuid(card_uuid, force_refresh=False, db_session=None): del force_refresh, db_session return None async def fake_save_card_to_db(card, async_session, commit=True): del async_session, commit saved_cards.append(card) card.card_id = 2 monkeypatch.setattr(service, "_init_database", fake_init_database) monkeypatch.setattr(service, "get_card_by_uuid", fake_get_card_by_uuid) monkeypatch.setattr(service, "_save_card_to_db", fake_save_card_to_db) new_card = await service.activate_card( card_uuid="CARD_B", device_id="TalkingQ_device001", db_session=session, ) assert existing.device_id == "TalkingQ_device001" assert existing.status == 1 assert new_card.card_uuid == "CARD_B" assert new_card.device_id == "TalkingQ_device001" assert new_card.status == 1 assert saved_cards == [new_card] @pytest.mark.asyncio async def test_activate_card_rejects_card_bound_to_other_device(monkeypatch): service = CardService() existing = Card( card_id=1, card_uuid="CARD_A", device_id="TalkingQ_device002", status=1, ) saved_cards = [] session = FakeSession() async def fake_init_database(): return None async def fake_get_card_by_uuid(card_uuid, force_refresh=False, db_session=None): del force_refresh, db_session return existing if card_uuid == "CARD_A" else None async def fake_save_card_to_db(card, async_session, commit=True): del async_session, commit saved_cards.append(card) monkeypatch.setattr(service, "_init_database", fake_init_database) monkeypatch.setattr(service, "get_card_by_uuid", fake_get_card_by_uuid) monkeypatch.setattr(service, "_save_card_to_db", fake_save_card_to_db) with pytest.raises(ValueError, match="card is already bound to another device"): await service.activate_card( card_uuid="CARD_A", device_id="TalkingQ_device001", db_session=session, ) assert existing.device_id == "TalkingQ_device002" assert saved_cards == [] @pytest.mark.asyncio async def test_is_active_for_device_requires_matching_active_card(monkeypatch): service = CardService() active_card = Card(card_uuid="CARD_A", device_id="TalkingQ_device001", status=1) inactive_card = Card(card_uuid="CARD_B", device_id="TalkingQ_device001", status=0) async def fake_get_card_by_uuid(card_uuid): return { "CARD_A": active_card, "CARD_B": inactive_card, "CARD_C": Card(card_uuid="CARD_C", device_id="TalkingQ_device002", status=1), }.get(card_uuid) monkeypatch.setattr(service, "get_card_by_uuid", fake_get_card_by_uuid) assert await service.is_active_for_device("CARD_A", "TalkingQ_device001") is True assert await service.is_active_for_device("CARD_B", "TalkingQ_device001") is False assert await service.is_active_for_device("CARD_C", "TalkingQ_device001") is False assert await service.is_active_for_device("CARD_MISSING", "TalkingQ_device001") is False