using Vanguard.Content.CardText; using Vanguard.Content.Translations; using Xunit; namespace Vanguard.Rules.Tests; public class CardTextTests { [Fact] public void Tokenizer_Replaces_Ability_And_Zone_Markers() { var template = CardTextTokenizer.ToTemplate( "[AUTO](VC/RC):[Counter-Blast 2] When this unit is placed on (RC), retire a rear-guard."); Assert.Equal( "{auto}{vcrc}:{cb:2} When this unit is placed on {rc}, retire a rear-guard.", template); } [Fact] public void Tokenizer_Handles_Numeric_Costs() { var template = CardTextTokenizer.ToTemplate("[ACT](VC):[Soul-Blast 8 & Counter-Blast 5] Draw up to five cards."); Assert.Contains("{sb:8}", template); Assert.Contains("{cb:5}", template); Assert.DoesNotContain("[", template); } [Fact] public void Tokenizer_Handles_Clan_Brackets_And_Source_Typo() { Assert.Equal("{clan:royal-paladin}", CardTextTokenizer.ToTemplate("")); Assert.Equal("{clan:royal-paladin}", CardTextTokenizer.ToTemplate("<")); Assert.Equal("{clan:spike-brothers}", CardTextTokenizer.ToTemplate("<")); } [Fact] public void Tokenizer_Keeps_Free_Text_Costs_Untouched() { var template = CardTextTokenizer.ToTemplate( "[ACT](RC):[Rest this unit & Choose a card from your hand, and discard it] Draw a card."); Assert.Equal( "{act}{rc}:[{rest} & Choose a card from your hand, and discard it] Draw a card.", template); } [Fact] public void Every_Template_Token_Exists_In_Keywords() { var keywords = KeywordCatalog.Load(TestPaths.Keywords); var catalog = TestCatalog.Instance; foreach (var card in catalog.Cards) { var template = CardTextTokenizer.ToTemplate(card.TextEn); foreach (var token in CardTextTokenizer.ExtractTokens(template).Keys) { var parts = token.Split(':', 2); var value = parts.Length > 1 ? parts[1] : null; Assert.True( keywords.ContainsToken(parts[0], value), $"{card.NameId}: токен {{{token}}} отсутствует в keywords.yaml"); } } } [Fact] public void Translation_Check_Flags_Broken_Tokens() { var file = new TranslationFile { Cards = { new TranslationEntry { NameId = "test", NameEn = "Test", NameRu = "Тест", Template = "{auto}{vc}:Draw a card.", TextRu = "Взять карту.", }, }, }; var report = TranslationService.Check(file); Assert.Contains(report.Issues, i => i.Code == "token.mismatch"); } [Fact] public void Translation_Check_Passes_On_Complete_Entry() { var file = new TranslationFile { Cards = { new TranslationEntry { NameId = "test", NameEn = "Test", NameRu = "Тест", Template = "{auto}{vc}:Draw a card.", TextRu = "{auto}{vc}:Взять карту.", }, }, }; var report = TranslationService.Check(file); Assert.True(report.IsComplete); } }