import tempfile import unittest import importlib.util import sys import types from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent def ensure_package(package_name: str, package_path: Path) -> None: if package_name in sys.modules: return package = types.ModuleType(package_name) package.__path__ = [str(package_path)] sys.modules[package_name] = package def load_module(module_name: str, relative_path: str): module_path = PROJECT_ROOT / relative_path spec = importlib.util.spec_from_file_location(module_name, module_path) module = importlib.util.module_from_spec(spec) assert spec and spec.loader sys.modules[module_name] = module spec.loader.exec_module(module) return module ensure_package("danding_bot", PROJECT_ROOT / "danding_bot") ensure_package("danding_bot.plugins", PROJECT_ROOT / "danding_bot/plugins") ensure_package( "danding_bot.plugins.onmyoji_gacha", PROJECT_ROOT / "danding_bot/plugins/onmyoji_gacha", ) load_module( "danding_bot.plugins.onmyoji_gacha.config", "danding_bot/plugins/onmyoji_gacha/config.py", ) data_manager_module = load_module( "danding_bot.plugins.onmyoji_gacha.data_manager", "danding_bot/plugins/onmyoji_gacha/data_manager.py", ) utils = load_module( "danding_bot.plugins.onmyoji_gacha.utils", "danding_bot/plugins/onmyoji_gacha/utils.py", ) class DataManagerSignInTests(unittest.TestCase): def setUp(self) -> None: self.temp_dir = tempfile.TemporaryDirectory() base_path = Path(self.temp_dir.name) self.original_db_file = data_manager_module.config.DB_FILE self.original_img_dir = data_manager_module.config.SHIKIGAMI_IMG_DIR data_manager_module.config.DB_FILE = str(base_path / "gacha.db") data_manager_module.config.SHIKIGAMI_IMG_DIR = str(base_path / "images") Path(data_manager_module.config.SHIKIGAMI_IMG_DIR).mkdir(parents=True, exist_ok=True) self.manager = data_manager_module.DataManager() def tearDown(self) -> None: data_manager_module.config.DB_FILE = self.original_db_file data_manager_module.config.SHIKIGAMI_IMG_DIR = self.original_img_dir self.temp_dir.cleanup() def test_record_sign_in_is_idempotent_for_same_day(self) -> None: user_id = "10001" self.assertFalse(self.manager.has_signed_in_today(user_id)) self.assertTrue(self.manager.record_sign_in(user_id, 88)) self.assertTrue(self.manager.has_signed_in_today(user_id)) self.assertFalse(self.manager.record_sign_in(user_id, 99)) class UtilsSignInTests(unittest.TestCase): def test_get_luck_description_uses_document_ranges(self) -> None: self.assertEqual(utils.get_luck_description(1), ("ιžι…‹", "😭")) self.assertEqual(utils.get_luck_description(11), ("δΈ€θˆ¬", "😐")) self.assertEqual(utils.get_luck_description(31), ("小欧", "😊")) self.assertEqual(utils.get_luck_description(61), ("倧欧", "πŸŽ‰")) self.assertEqual(utils.get_luck_description(91), ("ζ¬§ηš‡", "πŸ‘‘")) def test_format_sign_in_message_matches_required_format(self) -> None: message = utils.format_sign_in_message("10001", "小倏", 87, 1247) expected = ( "@小倏 πŸ“… 每ζ—₯签到成功!\n" "🎁 θŽ·εΎ—η§―εˆ†οΌš87\n" "πŸŽ‰ 今ζ—₯θΏζ°”οΌšε€§ζ¬§\n" "πŸ’° ε½“ε‰η§―εˆ†οΌš1247" ) self.assertEqual(message, expected) if __name__ == "__main__": unittest.main()