namespace HSchool.Content.Tests; public class CatalogLoaderTests { private readonly CatalogLoader _loader = new(); [Fact] public void Jsonc_AllowsCommentsAndTrailingCommas() { var catalog = _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def( CatalogLoader.CorePackId, "actions", "sit", """ // a verb the Sit system already knows { "defName": "Sit", "abstract": true, } """), ]); Assert.True(catalog.Actions.ContainsKey("Sit")); } [Fact] public void DuplicateDefName_LastPackWinsAndWarns() { var log = new RecordingLog(); var catalog = _loader.Load( [CatalogLoader.CorePackId, "addon"], [ PackDocuments.Def(CatalogLoader.CorePackId, "things", "chair", """{ "defName": "Chair", "actions": [] }"""), PackDocuments.Def("addon", "things", "chair", """{ "defName": "Chair", "actions": ["Sit"] }"""), PackDocuments.Def(CatalogLoader.CorePackId, "actions", "sit", """{ "defName": "Sit", "abstract": true }"""), ], log); Assert.Equal(["Sit"], catalog.Things["Chair"].Actions); Assert.Contains(log.Warnings, warning => warning.Contains("Chair") && warning.Contains("addon")); } [Fact] public void DuplicateLocaleKey_LastPackWinsAndWarns() { var log = new RecordingLog(); var catalog = _loader.Load( [CatalogLoader.CorePackId, "addon"], [ PackDocuments.Def(CatalogLoader.CorePackId, "actions", "sit", """{ "defName": "Sit", "abstract": true }"""), PackDocuments.Locale(CatalogLoader.CorePackId, "ru", """{ "Sit": "Сесть" }"""), PackDocuments.Locale("addon", "ru", """{ "Sit": "Присесть" }"""), ], log); Assert.Equal("Присесть", catalog.Label("ru", catalog.Actions["Sit"])); Assert.Contains(log.Warnings, warning => warning.Contains("Sit") && warning.Contains("addon")); } [Fact] public void Text_FallsBackToTheKeyWhenMissing() { var catalog = _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def(CatalogLoader.CorePackId, "actions", "sit", """{ "defName": "Sit", "abstract": true }"""), PackDocuments.Locale(CatalogLoader.CorePackId, "ru", """{ "Sit": "Сесть" }"""), ]); Assert.Equal("Сесть", catalog.Text("ru", "Sit")); Assert.Equal("Skinny", catalog.Text("en", "Skinny")); } [Fact] public void CoreIsAlwaysFirst_EvenIfOmittedFromThePackList() { var catalog = _loader.Load( ["addon"], [ PackDocuments.Def(CatalogLoader.CorePackId, "actions", "sit", """{ "defName": "Sit", "abstract": true }"""), PackDocuments.Def("addon", "actions", "wave", """{ "defName": "Wave", "abstract": true }"""), ]); Assert.Equal([CatalogLoader.CorePackId, "addon"], catalog.PackIds); Assert.True(catalog.Actions.ContainsKey("Sit")); Assert.True(catalog.Actions.ContainsKey("Wave")); } [Fact] public void ThingActions_MustExist() { var ex = Assert.Throws(() => _loader.Load( [CatalogLoader.CorePackId], [PackDocuments.Def(CatalogLoader.CorePackId, "things", "chair", """{ "defName": "Chair", "actions": ["Sit"] }""")])); Assert.Contains("Sit", ex.Message); } [Fact] public void RoomSlotsAndPositions_MustExist() { var ex = Assert.Throws(() => _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def( CatalogLoader.CorePackId, "rooms", "office", """{ "defName": "Office", "slots": [{ "key": "chair", "thing": "Chair" }], "positions": ["Principal"], "travelMinutes": 1 }"""), ])); Assert.Contains("Chair", ex.Message); } [Fact] public void Label_FallsBackToParentThenDefName() { var catalog = _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def(CatalogLoader.CorePackId, "things", "base", """{ "defName": "FurnitureBase", "abstract": true }"""), PackDocuments.Def(CatalogLoader.CorePackId, "things", "chair", """{ "defName": "Chair", "parent": "FurnitureBase" }"""), PackDocuments.Locale(CatalogLoader.CorePackId, "ru", """{ "FurnitureBase": "Мебель" }"""), ]); Assert.Equal("Мебель", catalog.Label("ru", catalog.Things["Chair"])); Assert.Equal("Chair", catalog.Label("en", catalog.Things["Chair"])); } [Fact] public void ConcreteRoomWithoutTravelMinutes_FailsTheCatalog() { var ex = Assert.Throws(() => _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def(CatalogLoader.CorePackId, "rooms", "office", """{ "defName": "Office" }"""), ])); Assert.Contains("travelMinutes", ex.Message, StringComparison.OrdinalIgnoreCase); } [Fact] public void ConcreteTerritoryWithoutTravelMinutes_FailsTheCatalog() { var ex = Assert.Throws(() => _loader.Load( [CatalogLoader.CorePackId], [ PackDocuments.Def(CatalogLoader.CorePackId, "territories", "yard", """{ "defName": "Yard" }"""), ])); Assert.Contains("travelMinutes", ex.Message, StringComparison.OrdinalIgnoreCase); } }