138 lines
4.1 KiB
C#
138 lines
4.1 KiB
C#
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("<Royal Paladin>"));
|
|
Assert.Equal("{clan:royal-paladin}", CardTextTokenizer.ToTemplate("<<Royal Paladin>"));
|
|
Assert.Equal("{clan:spike-brothers}", CardTextTokenizer.ToTemplate("<<Spike Brothers>"));
|
|
}
|
|
|
|
[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 = "Test",
|
|
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_Flags_Forbidden_Terms()
|
|
{
|
|
var file = new TranslationFile
|
|
{
|
|
Cards =
|
|
{
|
|
new TranslationEntry
|
|
{
|
|
NameId = "test",
|
|
NameEn = "Test",
|
|
Template = "{auto}{vc}:Draw a card.",
|
|
TextRu = "{auto}{vc}:Этот юнит берёт карту.",
|
|
},
|
|
},
|
|
};
|
|
|
|
var report = TranslationService.Check(file);
|
|
|
|
Assert.Contains(report.Issues, i => i.Code == "style.forbidden");
|
|
}
|
|
|
|
[Fact]
|
|
public void Translation_Check_Passes_On_Complete_Entry()
|
|
{
|
|
var file = new TranslationFile
|
|
{
|
|
Cards =
|
|
{
|
|
new TranslationEntry
|
|
{
|
|
NameId = "test",
|
|
NameEn = "Test",
|
|
NameRu = "Test",
|
|
Template = "{auto}{vc}:Draw a card.",
|
|
TextRu = "{auto}{vc}:Взять карту.",
|
|
},
|
|
},
|
|
};
|
|
|
|
var report = TranslationService.Check(file);
|
|
|
|
Assert.True(report.IsComplete);
|
|
}
|
|
}
|