import unittest from pathlib import Path from tempfile import TemporaryDirectory from types import SimpleNamespace from unittest.mock import patch from app.danmu_queue import BgiLogMonitor, WebServer class BgiLogDisplayFormatTests(unittest.TestCase): def test_formats_multi_instance_log_as_single_readable_line(self): raw_lines = [ "[23:55:25.160] [INF] [Primary:S1:P16720:T1785426828552] " "BetterGenshinImpact.GameTask.TaskTriggerDispatcher\n", "游戏已退出,BetterGI 自动停止截图器\n", "\n", ] self.assertEqual( BgiLogMonitor.format_display_lines(raw_lines), ["[23:55:25] 游戏已退出,BetterGI 自动停止截图器"], ) def test_formats_legacy_log_header_the_same_way(self): raw_lines = [ "[16:39:12.328] [INF] BetterGenshinImpact.GameTask.TaskTriggerDispatcher\n", "游戏已退出,BetterGI 自动停止截图器\n", ] self.assertEqual( BgiLogMonitor.format_display_lines(raw_lines), ["[16:39:12] 游戏已退出,BetterGI 自动停止截图器"], ) def test_preserves_multiline_message_inside_one_log_entry(self): raw_lines = [ "[10:00:00.001] [ERR] [Primary:S1:P1:T2] BetterGI.Component\n", "第一行\n", "第二行\n", "[10:00:01.999] [INF] BetterGI.OtherComponent\n", "下一条\n", ] self.assertEqual( BgiLogMonitor.format_display_lines(raw_lines), ["[10:00:00] 第一行\n第二行", "[10:00:01] 下一条"], ) def test_frontend_reader_falls_back_to_latest_log_after_midnight(self): with TemporaryDirectory() as temp_dir: log_dir = Path(temp_dir) / "log" log_dir.mkdir() (log_dir / "better-genshin-impact20260730.log").write_text( "[23:55:25.160] [INF] [Primary:S1:P16720:T1785426828552] " "BetterGenshinImpact.GameTask.TaskTriggerDispatcher\n" "游戏已退出,BetterGI 自动停止截图器\n", encoding="utf-8", ) server = WebServer.__new__(WebServer) server.config = SimpleNamespace(bettergi_work_dir=temp_dir) with patch("app.danmu_queue.datetime") as mocked_datetime: mocked_datetime.now.return_value.strftime.return_value = "20260731" result = server._read_bgi_log(50) self.assertEqual( result, ["[23:55:25] 游戏已退出,BetterGI 自动停止截图器"], ) if __name__ == "__main__": unittest.main()