"""Tests for the notification store's per-user read-state contract. These pin the core property that makes broadcast-to-everyone work without a subscription model: one notification row is shared by all users, and each user's read state is tracked independently against it. """ from __future__ import annotations from app.infrastructure.perception.mock_notification_store import MockNotificationStore def _store_with_one_notification() -> MockNotificationStore: store = MockNotificationStore() store.create( event_id="evt-001", kind="new", title="《电动汽车安全要求》国家标准第三版正式发布", impact_level="high", summary=None, ) return store def test_a_new_notification_is_unread_for_everyone(): """Nobody has read it yet, so unread_count is 1 for any user.""" store = _store_with_one_notification() assert store.unread_count("user-a") == 1 assert store.unread_count("user-b") == 1 def test_mark_all_read_zeroes_the_count_for_that_user(): """Reading clears the count for the user who read it.""" store = _store_with_one_notification() marked = store.mark_all_read("user-a") assert marked == 1 assert store.unread_count("user-a") == 0 def test_one_users_read_state_does_not_affect_another(): """The whole point of read receipts over per-user fan-out: independence.""" store = _store_with_one_notification() store.mark_all_read("user-a") assert store.unread_count("user-a") == 0 assert store.unread_count("user-b") == 1 def test_list_for_user_reports_the_read_flag_correctly(): """The list endpoint must reflect this user's own read state per item.""" store = _store_with_one_notification() store.mark_all_read("user-a") items_a = store.list_for_user("user-a") items_b = store.list_for_user("user-b") assert len(items_a) == 1 assert items_a[0]["read"] is True assert items_b[0]["read"] is False def test_list_for_user_orders_newest_first(): """Notifications appear most-recent-first regardless of creation order.""" store = MockNotificationStore() store.create(event_id="evt-1", kind="new", title="first", impact_level="low", summary=None) store.create(event_id="evt-2", kind="new", title="second", impact_level="low", summary=None) items = store.list_for_user("user-a") assert [item["title"] for item in items] == ["second", "first"] def test_mark_all_read_is_a_no_op_on_an_empty_feed(): """Reading an empty feed must not raise and reports zero marked.""" store = MockNotificationStore() assert store.mark_all_read("user-a") == 0 def test_mark_all_read_does_not_recount_already_read_notifications(): """Calling mark_all_read twice must not double-count as newly marked.""" store = _store_with_one_notification() first = store.mark_all_read("user-a") second = store.mark_all_read("user-a") assert first == 1 assert second == 0