Updated the CI workflow to run tests for individual projects, ensuring accurate coverage reports are generated for each module. Enhanced the BumperPlaceholders class to handle dangling separators more effectively, improving text resolution logic and maintaining clarity in output.
137 lines
5.0 KiB
C#
137 lines
5.0 KiB
C#
using TeleWave.Application.Broadcast.Bumpers;
|
||
using TeleWave.Application.Common.Interfaces;
|
||
using TeleWave.Domain.Broadcast;
|
||
using Xunit;
|
||
|
||
namespace TeleWave.Application.Tests.Broadcast;
|
||
|
||
/// <summary>
|
||
/// Подстановка плейсхолдеров. Правило одно и важное: неизвестное значение схлопывается вместе
|
||
/// с осиротевшим разделителем, а не оставляет дыру в кадре.
|
||
/// </summary>
|
||
public class BumperPlaceholdersTests
|
||
{
|
||
private static readonly DateTimeOffset Moment = new(
|
||
2026,
|
||
4,
|
||
6,
|
||
21,
|
||
24,
|
||
0,
|
||
TimeSpan.FromHours(3)
|
||
);
|
||
|
||
private static BumperContext Full() =>
|
||
new(
|
||
"Первый",
|
||
4,
|
||
Moment,
|
||
"Симпсоны",
|
||
"Терминатор 2",
|
||
"с5э12",
|
||
"с1э3",
|
||
1991,
|
||
"Боевик",
|
||
new TimeOnly(21, 30),
|
||
"Вечернее кино"
|
||
);
|
||
|
||
[Theory]
|
||
[InlineData("{channel}", "Первый")]
|
||
[InlineData("{channel.number}", "4")]
|
||
[InlineData("{now.title}", "Симпсоны")]
|
||
[InlineData("{next.title}", "Терминатор 2")]
|
||
[InlineData("{now.episode}", "с5э12")]
|
||
[InlineData("{next.episode}", "с1э3")]
|
||
[InlineData("{next.year}", "1991")]
|
||
[InlineData("{next.genre}", "Боевик")]
|
||
[InlineData("{next.time}", "21:30")]
|
||
[InlineData("{time}", "21:24")]
|
||
[InlineData("{date}", "6 апреля")]
|
||
[InlineData("{weekday}", "понедельник")]
|
||
[InlineData("{slot}", "Вечернее кино")]
|
||
public void Resolve_SubstitutesEveryToken(string text, string expected) =>
|
||
Assert.Equal(expected, BumperPlaceholders.Resolve(text, Full()));
|
||
|
||
[Fact]
|
||
public void Resolve_MixesTextAndTokens()
|
||
{
|
||
var resolved = BumperPlaceholders.Resolve("ДАЛЕЕ В {next.time} — {next.title}", Full());
|
||
|
||
Assert.Equal("ДАЛЕЕ В 21:30 — Терминатор 2", resolved);
|
||
}
|
||
|
||
[Fact]
|
||
public void Resolve_CollapsesGapsFromMissingValues()
|
||
{
|
||
var empty = new BumperContext("Канал", null, Moment);
|
||
|
||
// Ни следующей программы, ни номера канала: строка схлопывается, осиротевший разделитель уходит.
|
||
Assert.Equal("СЕЙЧАС", BumperPlaceholders.Resolve("СЕЙЧАС — {now.title}", empty));
|
||
Assert.Equal("", BumperPlaceholders.Resolve("{next.title}", empty));
|
||
Assert.Equal("Канал", BumperPlaceholders.Resolve("{channel} {channel.number}", empty));
|
||
// А висящий предлог остаётся: отличить его от слова в чужом тексте нельзя.
|
||
Assert.Equal("ДАЛЕЕ В", BumperPlaceholders.Resolve("ДАЛЕЕ В {next.time}", empty));
|
||
}
|
||
|
||
[Fact]
|
||
public void Resolve_UnknownTokenBecomesEmpty()
|
||
{
|
||
Assert.Equal("Далее", BumperPlaceholders.Resolve("Далее {next.tittle}", Full()));
|
||
Assert.Equal("", BumperPlaceholders.Resolve(" ", Full()));
|
||
}
|
||
|
||
[Fact]
|
||
public void UnknownTokens_ListsOnlyStrangers()
|
||
{
|
||
Assert.Equal(
|
||
["next.tittle", "chanel"],
|
||
BumperPlaceholders.UnknownTokens("{next.title} {next.tittle} {chanel} {next.tittle}")
|
||
);
|
||
Assert.Empty(BumperPlaceholders.UnknownTokens("{channel}"));
|
||
Assert.Empty(BumperPlaceholders.UnknownTokens(null));
|
||
}
|
||
|
||
[Fact]
|
||
public void TokensIn_CollectsAcrossTexts()
|
||
{
|
||
var tokens = BumperPlaceholders.TokensIn(["СЕЙЧАС {now.title}", "", "{next.genre}"]);
|
||
|
||
Assert.Equal(["next.genre", "now.title"], tokens.Order());
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData("{time}", true)]
|
||
[InlineData("{date}", true)]
|
||
[InlineData("{weekday}", true)]
|
||
[InlineData("{next.time}", false)]
|
||
[InlineData("СЕЙЧАС", false)]
|
||
[InlineData(null, false)]
|
||
public void IsVolatile_MarksTokensTiedToTheMoment(string? text, bool expected) =>
|
||
Assert.Equal(expected, BumperPlaceholders.IsVolatile(text));
|
||
|
||
[Theory]
|
||
[InlineData(5, 12, "с5э12")]
|
||
[InlineData(null, 7, "э7")]
|
||
[InlineData(3, null, null)]
|
||
[InlineData(null, null, null)]
|
||
public void Episode_FormatsWhatIsKnown(int? season, int? episode, string? expected) =>
|
||
Assert.Equal(expected, BumperPlaceholders.Episode(season, episode));
|
||
|
||
[Fact]
|
||
public void RenderedText_RoundTripsAndSurvivesGarbage()
|
||
{
|
||
var lines = new List<BumperRenderLine>
|
||
{
|
||
new(BumperLineStyle.Label, BumperLineColor.Accent, "СЕЙЧАС"),
|
||
new(BumperLineStyle.Title, BumperLineColor.Text, "Симпсоны"),
|
||
};
|
||
|
||
var restored = BumperRenderedText.FromJson(BumperRenderedText.ToJson(lines));
|
||
|
||
Assert.Equal(lines, restored);
|
||
Assert.Empty(BumperRenderedText.FromJson("{не json}"));
|
||
Assert.Empty(BumperRenderedText.FromJson(null));
|
||
}
|
||
}
|