Files
xiaobai-review/tests/test_alerts.py
T

97 lines
3.7 KiB
Python

from __future__ import annotations
import tempfile
import unittest
from pathlib import Path
from backend.features.alerts.service import AlertService
from database import ReviewDatabase
class AlertServiceTests(unittest.TestCase):
def setUp(self) -> None:
self.temp = tempfile.TemporaryDirectory()
self.database = ReviewDatabase(Path(self.temp.name) / "review.db")
self.owner = self.database.create_user("alert_owner", "salt", "hash")
self.other = self.database.create_user("alert_other", "salt", "hash")
self.service = AlertService(self.database)
def tearDown(self) -> None:
self.temp.cleanup()
def test_future_manual_alert_is_visible_but_not_unread_until_due(self):
alert_id = self.service.create_manual(
self.owner["id"],
{
"title": "复核承接",
"content": "开盘不及预期则退出观察",
"code": "002141",
"remind_date": "2026-07-25",
},
)
before = self.service.list_alerts(self.owner["id"], "all", "2026-07-22")
due = self.service.list_alerts(self.owner["id"], "unread", "2026-07-25")
self.assertEqual(before["items"][0]["id"], alert_id)
self.assertFalse(before["items"][0]["due"])
self.assertEqual(before["unread_count"], 0)
self.assertEqual(due["unread_count"], 1)
self.assertTrue(due["items"][0]["due"])
def test_alert_reads_and_mutations_are_scoped_to_owner(self):
alert_id = self.database.save_alert(
self.owner["id"], "manual", "甲的提醒", "", "20260722", "", "owner-only"
)
self.assertEqual(
self.service.list_alerts(self.other["id"], "all", "2026-07-22")["items"], []
)
self.assertFalse(self.database.mark_alert_read(self.other["id"], alert_id))
self.assertFalse(self.database.delete_alert(self.other["id"], alert_id))
self.assertTrue(self.database.mark_alert_read(self.owner["id"], alert_id))
self.assertEqual(
self.service.list_alerts(self.owner["id"], "all", "2026-07-22")["unread_count"], 0
)
self.assertTrue(self.database.delete_alert(self.owner["id"], alert_id))
def test_strategy_alerts_are_idempotent(self):
tracking = {
"batches": [
{
"run_id": 9,
"strategy_name": "修复策略",
"items": [{"code": "002141"}, {"code": "600000"}],
"summary": {
"observed": 2,
"completed": 2,
"t1_win_rate": 50.0,
"average_t5": 3.25,
},
}
]
}
self.service.sync_strategy_tracking(self.owner["id"], tracking)
self.service.sync_strategy_tracking(self.owner["id"], tracking)
alerts = self.database.list_alerts(
self.owner["id"], "99991231", unread_only=False
)
self.assertEqual(len(alerts), 2)
self.assertEqual({item["kind"] for item in alerts}, {"strategy_t1", "strategy_t5"})
def test_mark_all_only_changes_due_alerts(self):
self.database.save_alert(
self.owner["id"], "manual", "今日", "", "20260722", "", "due"
)
self.database.save_alert(
self.owner["id"], "manual", "未来", "", "20260723", "", "future"
)
self.assertEqual(
self.database.mark_all_alerts_read(self.owner["id"], "20260722"), 1
)
future = self.service.list_alerts(self.owner["id"], "unread", "2026-07-23")
self.assertEqual([item["title"] for item in future["items"]], ["未来"])
if __name__ == "__main__":
unittest.main()