#!/usr/bin/env python3 """Unit tests for WolfDawn database classification in util/wolfdawn/db_classify.py.""" from __future__ import annotations import json import os import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] os.chdir(ROOT) sys.path.insert(0, str(ROOT)) from util.wolfdawn import db_classify as wdb # noqa: E402 STANDARD_DB = { "file": "DataBase.project", "kind": "db", "groups": [ { "type": 0, "typeName": "Skill · 技能", "lines": [ { "row": 2, "field": 1, "fieldName": "Description · 説明", "source": "味方一人のHPを回復", "text": "味方一人のHPを回復", }, ], }, { "type": 1, "typeName": "Item · アイテム", "lines": [ { "row": 0, "field": 1, "fieldName": "Description · 説明", "source": "HPを回復", "text": "HPを回復", }, ], }, ], } NARRATIVE_DB = { "file": "DataBase.project", "kind": "db", "groups": [ { "type": 10, "typeName": "■イベント(セルリア)", "lines": [ { "row": 0, "field": 3, "fieldName": "セリフ_メッセージ", "source": "こんにちは", "text": "こんにちは", }, { "row": 0, "field": 4, "fieldName": "直前の相手_コメント", "source": "誰か", "text": "誰か", }, ], }, { "type": 11, "typeName": "├■プロフィール(元数値)", "lines": [ { "row": 1, "field": 2, "fieldName": "好きなもの_コメント", "source": "甘いもの", "text": "甘いもの", }, ], }, ], } class TestClassifyGroupTier(unittest.TestCase): def test_standard_skill_sheet_is_foundation(self): tier = wdb.classify_group_tier( "Skill · 技能", STANDARD_DB["groups"][0]["lines"], ) self.assertEqual(tier, wdb.TIER_FOUNDATION) def test_custom_event_sheet_is_narrative(self): tier = wdb.classify_group_tier( "■イベント(セルリア)", NARRATIVE_DB["groups"][0]["lines"], ) self.assertEqual(tier, wdb.TIER_NARRATIVE) def test_profile_sheet_is_narrative(self): tier = wdb.classify_group_tier( "├■プロフィール(元数値)", NARRATIVE_DB["groups"][1]["lines"], ) self.assertEqual(tier, wdb.TIER_NARRATIVE) class TestClassifyDbDocument(unittest.TestCase): def test_standard_doc_groups(self): groups = wdb.classify_db_document(STANDARD_DB) self.assertEqual(len(groups), 2) self.assertTrue(all(g.tier == wdb.TIER_FOUNDATION for g in groups)) self.assertTrue(all(g.default_checked for g in groups)) def test_narrative_doc_groups(self): groups = wdb.classify_db_document(NARRATIVE_DB) self.assertEqual(len(groups), 2) self.assertTrue(all(g.tier == wdb.TIER_NARRATIVE for g in groups)) self.assertTrue(all(not g.default_checked for g in groups)) class TestContentDistribution(unittest.TestCase): def test_analyze_mixed_files_dir(self): with tempfile.TemporaryDirectory() as tmp: base = Path(tmp) (base / "DataBase.project.json").write_text( json.dumps({**STANDARD_DB, **NARRATIVE_DB, "groups": ( STANDARD_DB["groups"] + NARRATIVE_DB["groups"] )}, ensure_ascii=False), encoding="utf-8", ) (base / "OP.mps.json").write_text( json.dumps({ "file": "OP.mps", "kind": "map", "scenes": [{"lines": [{"source": "a", "text": "a"}]}], }), encoding="utf-8", ) dist = wdb.analyze_content_distribution(base) self.assertGreater(dist.db_lines, 0) self.assertGreater(dist.db_foundation_lines, 0) self.assertGreater(dist.db_narrative_lines, 0) self.assertEqual(dist.map_files, 1) self.assertEqual(dist.map_lines, 1) def test_discovery_summary_mentions_database(self): with tempfile.TemporaryDirectory() as tmp: base = Path(tmp) (base / "DataBase.project.json").write_text( json.dumps(NARRATIVE_DB, ensure_ascii=False), encoding="utf-8", ) dist = wdb.analyze_content_distribution(base) summary = wdb.format_discovery_summary(dist) self.assertIn("Database:", summary) self.assertIn("Recommended order:", summary) class TestGroupFilter(unittest.TestCase): def test_group_key_format(self): key = wdb.group_key("DataBase.project.json", "Skill · 技能") self.assertEqual(key, "DataBase.project.json|Skill · 技能") def test_filter_by_groups(self): groups = frozenset({"DataBase.project.json|Skill · 技能"}) self.assertTrue( wdb.group_matches_filter( "DataBase.project.json", "Skill · 技能", frozenset(), groups ) ) self.assertFalse( wdb.group_matches_filter( "DataBase.project.json", "■イベント(セルリア)", frozenset(), groups ) ) def test_empty_filter_matches_all(self): self.assertTrue( wdb.group_matches_filter( "DataBase.project.json", "■イベント(セルリア)", frozenset(), frozenset() ) ) class TestDbProfile(unittest.TestCase): def test_save_and_load_profile(self): with tempfile.TemporaryDirectory() as tmp: work = Path(tmp) profile = { "archetype": "simulation_db_heavy", "foundation_groups": ["DataBase.project.json|Skill · 技能"], "narrative_groups": ["DataBase.project.json|■イベント(セルリア)"], "defer_groups": [], "notes": "Test note", } wdb.save_db_profile(work, profile) loaded = wdb.load_db_profile(work) self.assertEqual(loaded["archetype"], "simulation_db_heavy") self.assertEqual(len(loaded["foundation_groups"]), 1) def test_import_ai_profile_strips_fences(self): raw = '```json\n{"archetype": "hybrid", "foundation_groups": []}\n```' data = wdb.import_ai_profile(raw) self.assertEqual(data["archetype"], "hybrid") def test_merge_profile_checks(self): groups = wdb.classify_db_document(NARRATIVE_DB) checks = wdb.merge_profile_with_groups( {"narrative_groups": [groups[0].key]}, groups, ) self.assertTrue(checks[groups[0].key]) self.assertFalse(checks[groups[1].key]) if __name__ == "__main__": unittest.main()