131 lines
6.2 KiB
Python
131 lines
6.2 KiB
Python
from tests.support import * # noqa: F401,F403
|
|
from nte_history_exporter.mappings import ACHIEVEMENTS
|
|
|
|
|
|
class MappingAndUpdateTests(unittest.TestCase):
|
|
def test_pool_mapping_json_files_have_uniform_shape(self):
|
|
required_top_level = {"pool_key", "game", "system", "banner", "request", "response"}
|
|
for pool_key, mapping in load_pool_mappings().items():
|
|
with self.subTest(pool_key=pool_key):
|
|
self.assertEqual(set(required_top_level) - set(mapping), set())
|
|
self.assertEqual(mapping["pool_key"], pool_key)
|
|
self.assertIn("id", mapping["system"])
|
|
self.assertIn("name", mapping["system"])
|
|
self.assertIn("id", mapping["banner"])
|
|
self.assertIn("name", mapping["banner"])
|
|
self.assertIn("shared_pity", mapping["banner"])
|
|
self.assertIn("family", mapping["request"])
|
|
self.assertIn("length", mapping["request"])
|
|
self.assertIn("constant", mapping["request"])
|
|
self.assertIn("cursor_step", mapping["request"])
|
|
|
|
def test_pool_mapping_json_matches_runtime_pool_meta(self):
|
|
for pool_key, mapping in load_pool_mappings().items():
|
|
with self.subTest(pool_key=pool_key):
|
|
self.assertEqual(pool_meta_from_mapping(mapping), POOL_META[pool_key])
|
|
|
|
def test_update_version_comparison_handles_release_tags(self):
|
|
self.assertTrue(is_newer_version("v0.1.7", "0.1.6"))
|
|
self.assertTrue(is_newer_version("0.2.0", "0.1.6"))
|
|
self.assertTrue(is_newer_version("v0.1.10", "0.1.9"))
|
|
self.assertFalse(is_newer_version("v0.1.6", "0.1.6"))
|
|
self.assertFalse(is_newer_version("v0.1.5", "0.1.6"))
|
|
self.assertFalse(is_newer_version("latest", "0.1.6"))
|
|
|
|
def test_update_check_reports_newer_github_release(self):
|
|
latest = {
|
|
"tag_name": "v0.1.7",
|
|
"html_url": "https://github.com/Golumpa/nte-exporter/releases/tag/v0.1.7",
|
|
}
|
|
with patch("nte_history_exporter.update_check.fetch_latest_release", return_value=latest):
|
|
update = check_for_update("0.1.6", timeout=0.1)
|
|
|
|
self.assertEqual(
|
|
update,
|
|
UpdateInfo(
|
|
current_version="0.1.6",
|
|
latest_version="v0.1.7",
|
|
release_url="https://github.com/Golumpa/nte-exporter/releases/tag/v0.1.7",
|
|
),
|
|
)
|
|
|
|
def test_update_check_ignores_prerelease(self):
|
|
latest = {
|
|
"tag_name": "v0.1.8-dev-branch.123",
|
|
"html_url": "https://github.com/Golumpa/nte-exporter/releases/tag/v0.1.8-dev-branch.123",
|
|
"prerelease": True,
|
|
}
|
|
with patch("nte_history_exporter.update_check.fetch_latest_release", return_value=latest):
|
|
self.assertIsNone(check_for_update("0.1.7", timeout=0.1))
|
|
|
|
def test_update_check_is_quiet_when_unavailable_or_current(self):
|
|
with patch("nte_history_exporter.update_check.fetch_latest_release", side_effect=OSError("offline")):
|
|
self.assertIsNone(check_for_update("0.1.6", timeout=0.1))
|
|
|
|
with patch("nte_history_exporter.update_check.fetch_latest_release", return_value={"tag_name": "v0.1.6"}):
|
|
self.assertIsNone(check_for_update("0.1.6", timeout=0.1))
|
|
|
|
def test_reward_mapping_files_have_expected_shape(self):
|
|
self.assertTrue(ARC_META)
|
|
for arc_id, meta in ARC_META.items():
|
|
with self.subTest(arc_id=arc_id):
|
|
self.assertTrue(arc_id.startswith("fork_"))
|
|
self.assertIn("name", meta)
|
|
self.assertIn(meta.get("rank"), ("S", "A", "B"))
|
|
|
|
self.assertTrue(CHARACTERS)
|
|
for character_id, info in CHARACTERS.items():
|
|
with self.subTest(character_id=character_id):
|
|
self.assertTrue(character_id.isdigit())
|
|
self.assertIn("name", info)
|
|
self.assertIn(info.get("rank"), ("S", "A"))
|
|
|
|
self.assertTrue(ACHIEVEMENTS)
|
|
battle_25 = ACHIEVEMENTS["battle_25"]
|
|
self.assertEqual(battle_25["name"], "Devil Within II")
|
|
self.assertEqual(battle_25["target"], 50)
|
|
self.assertEqual(
|
|
battle_25["rewards"], [{"item_id": "Annulith", "amount": 10}]
|
|
)
|
|
|
|
self.assertTrue(ITEMS)
|
|
for item_id, info in ITEMS.items():
|
|
with self.subTest(item_id=item_id):
|
|
self.assertIn(info.get("type"), ("item", "cosmetic"))
|
|
self.assertIn("name", info)
|
|
|
|
def test_rewards_by_id_merges_all_mapping_files(self):
|
|
for reward_id in (*ARC_META, *CHARACTERS, *ITEMS):
|
|
with self.subTest(reward_id=reward_id):
|
|
reward = REWARDS_BY_ID[reward_id]
|
|
self.assertEqual(reward["id"], reward_id)
|
|
self.assertIn(reward["type"], ("arc", "character", "item", "cosmetic"))
|
|
|
|
def test_decode_reward_key_round_trips_observed_keys(self):
|
|
observed = {
|
|
"98bdc9ad7dd9a5b99501": "fork_vine",
|
|
"98bdc9ad7d41c9bdad85c9e5bdb901": "fork_Prokaryon",
|
|
"98bdc9ad7ddda1d585add585b99d01": "fork_whuakuang",
|
|
"98bdc9ad7dddd5a1d585add585b99d01": "fork_wuhuakuang",
|
|
"10a58d9539bdc9b585b101": "DiceNormal",
|
|
"10a58d957dd1a58dad95d17dc1c400": "Dice_ticket_01",
|
|
"10a58d957dd1a58dad95d17dc1c800": "Dice_ticket_02",
|
|
"10a58d95b1a5b5a5d19501": "Dicelimite",
|
|
"1885cda1a5bdb97d1db1a591957dc5c0c4c000": "Fashion_Glide_1010",
|
|
"1885cda1a5bdb97dd995a1a58db1957dc5c0c4c07c59c1c0e000": "Fashion_vehicle_1010_V008",
|
|
"c4c0cccc00": "1033",
|
|
"c4c0dcc000": "1070",
|
|
"c4c0dcc0": "1070",
|
|
"c4c0c8c4": "1021",
|
|
}
|
|
for key_hex, expected_id in observed.items():
|
|
with self.subTest(key_hex=key_hex):
|
|
self.assertEqual(decode_reward_key(bytes.fromhex(key_hex)), expected_id)
|
|
|
|
def test_infer_reward_type_for_unmapped_ids(self):
|
|
self.assertEqual(infer_reward_type("fork_newarc"), "arc")
|
|
self.assertEqual(infer_reward_type("1099"), "character")
|
|
self.assertEqual(infer_reward_type("Fashion_hat_2000"), "cosmetic")
|
|
self.assertEqual(infer_reward_type("Dice_ticket_03"), "item")
|
|
self.assertEqual(infer_reward_type(""), "")
|
|
|