using NSubstitute; using TeleWave.Application.Common.Interfaces; using TeleWave.Application.Programming.Groups; using TeleWave.Application.Programming.Templates; using TeleWave.Application.Programming.Templates.Generate; using TeleWave.Application.Programming.Templates.Transfer; using TeleWave.Application.Tests.Support; using TeleWave.Domain.Broadcast; using TeleWave.Domain.Programming; using Xunit; namespace TeleWave.Application.Tests.Programming; /// /// Обмен конфигурацией там, где обмениваться нечем: нет канала, нет шаблона, нет источника /// метаданных. Всё это штатные исходы — админ открыл экран на канале, который ещё не настроен. /// public class TransferGuardsTests { private static readonly DateTimeOffset T0 = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero); private static ExportGridQueryHandler Export(IAppDbContext db) => new(db, GroupServices.Dynamic(db)); [Fact] public async Task Export_FailsWithoutChannel() { var fixture = new TestDb(); await using var db = fixture.New(); var result = await Export(db) .Handle(new ExportGridQuery(Guid.NewGuid()), CancellationToken.None); Assert.False(result.IsSuccess); } [Fact] public async Task Export_FailsWithoutTemplate() { // Канал без сетки выгружать нечем — и это отдельная ошибка, а не пустой файл. var fixture = new TestDb(); var channel = Channel.Create("Первый", "first", T0); await using (var seed = fixture.New()) { seed.Channels.Add(channel); await seed.SaveChangesAsync(CancellationToken.None); } await using var db = fixture.New(); var result = await Export(db) .Handle(new ExportGridQuery(channel.Id), CancellationToken.None); Assert.False(result.IsSuccess); } [Fact] public async Task Import_FailsWithoutTemplate() { var fixture = new TestDb(); await using var db = fixture.New(); var config = new GridConfig([new GridConfigLayer("Основная сетка", 10, [])]); var result = await new ImportGridCommandHandler( db, GroupServices.Slots(db), GroupServices.Stats(db), GroupServices.Interstitials(db) ).Handle(new ImportGridCommand(Guid.NewGuid(), config, false), CancellationToken.None); Assert.False(result.IsSuccess); } [Fact] public async Task Prompt_FailsWithoutChannel() { var fixture = new TestDb(); await using var db = fixture.New(); var result = await new BuildGridPromptQueryHandler(db, Catalog(db)).Handle( new BuildGridPromptQuery(Guid.NewGuid(), [], null), CancellationToken.None ); Assert.False(result.IsSuccess); } [Fact] public async Task Prompt_SaysWhatIsMissing_OnEmptyLibrary() { // Пустая библиотека — не ошибка: запрос собирается, но честно говорит, что групп нет, // иначе модель придумает их сама и вернёт сетку под несуществующий контент. var fixture = new TestDb(); var channel = Channel.Create("Первый", "first", T0); await using (var seed = fixture.New()) { seed.Channels.Add(channel); await seed.SaveChangesAsync(CancellationToken.None); } await using var db = fixture.New(); var result = await new BuildGridPromptQueryHandler(db, Catalog(db)).Handle( new BuildGridPromptQuery(channel.Id, [], null), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Equal(0, result.Value.Groups); Assert.Equal(0, result.Value.Shows); Assert.Contains("Готовых групп нет", result.Value.Prompt, StringComparison.Ordinal); Assert.Contains("Библиотека пуста", result.Value.Prompt, StringComparison.Ordinal); // Стыков и заставок тоже нет — модель должна знать, что ссылаться не на что. Assert.Contains("стыков ещё нет", result.Value.Prompt, StringComparison.Ordinal); } private static GroupCatalog Catalog(IAppDbContext db) => new(db, GroupServices.Dynamic(db), new GroupElementResolver(db)); }