from __future__ import annotations import tempfile import threading import unittest from pathlib import Path from unittest.mock import patch from database import ReviewDatabase from server import DashboardService class HeavenReadingTests(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("heaven_owner", "salt", "hash") self.other = self.database.create_user("heaven_other", "salt", "hash") def tearDown(self) -> None: self.temp.cleanup() def save(self, user_id: int, dedupe_key: str = "fortune:20260723") -> dict: return self.database.save_heaven_reading( user_id, "fortune", "20260723", "2026-07-23 观气", "丙午年 · 乙未月 · 己丑日", "当日解运结果", {"calendar_date": "20260723"}, dedupe_key, ) def test_history_is_private_and_delete_requires_ownership(self): reading = self.save(self.owner["id"]) self.assertEqual( self.database.list_heaven_readings(self.owner["id"], "fortune")[0]["answer"], "当日解运结果", ) self.assertEqual( self.database.list_heaven_readings(self.other["id"], "fortune"), [] ) self.assertFalse( self.database.delete_heaven_reading(self.other["id"], reading["id"]) ) self.assertTrue( self.database.delete_heaven_reading(self.owner["id"], reading["id"]) ) def test_fortune_dedupe_keeps_the_first_successful_result(self): first = self.save(self.owner["id"]) second = self.database.save_heaven_reading( self.owner["id"], "fortune", "20260723", "replacement", "replacement", "不应覆盖", {}, "fortune:20260723", ) self.assertEqual(second["id"], first["id"]) self.assertEqual(second["answer"], "当日解运结果") def test_fortune_interpretation_reuses_saved_result_before_llm(self): existing = self.save(self.owner["id"]) service = DashboardService.__new__(DashboardService) service.database = self.database service._request_context = threading.local() service._request_context.user_id = self.owner["id"] with patch.object(service, "heaven_setup") as setup, patch.object( service, "_call_heaven_agent" ) as call_agent: result = service.heaven_interpret( {"mode": "fortune", "trade_date": "2026-07-23"} ) setup.assert_not_called() call_agent.assert_not_called() self.assertTrue(result["reused"]) self.assertEqual(result["reading"]["id"], existing["id"]) self.assertEqual(result["answer"], "当日解运结果") if __name__ == "__main__": unittest.main()