Files
ersatztv/ErsatzTV.Tests/Infrastructure/GraphicsElementSeederTests.cs
T
timothyandtimothy ba6a4b08aa
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Skipped
Build ErsatzTV Image / CI toolchain image resolves (push) Successful in 9s
Build ErsatzTV Image / Delimiter ban (release path) (push) Successful in 25s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 8m40s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 6m18s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (push) Successful in 6m12s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m13s
probe742/combined-newest SECOND
feat(732): On Now / Next gets a background box, and is on by default (#843)
Co-authored-by: Timothy <timothy@noreply.gitea.tblindustries.be>
2026-08-26 19:28:25 +00:00

97 lines
3.7 KiB
C#

using System.IO.Abstractions;
using Testably.Abstractions.Testing;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Streaming.Graphics;
using ErsatzTV.Tests.Support;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Abstractions;
using NUnit.Framework;
using Shouldly;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using ErsatzTV.Core.Graphics;
namespace ErsatzTV.Tests.Infrastructure;
[TestFixture]
public class GraphicsElementSeederTests
{
private InMemoryTvContext _db = null!;
private string _seededPath = null!;
[SetUp]
public async Task SetUp()
{
_db = await InMemoryTvContext.CreateAsync();
_seededPath = Path.Combine(FileSystemLayout.GraphicsElementsTextTemplatesFolder, "on-now-next.yml");
}
[TearDown]
public async Task TearDown() => await _db.DisposeAsync();
[Test]
public async Task Seeds_File_And_Marker_When_Absent()
{
var fs = new MockFileSystem();
await using TvContext context = _db.CreateContext();
await GraphicsElementSeeder.SeedOnNowNext(context, fs, NullLogger.Instance, CancellationToken.None);
fs.File.Exists(_seededPath).ShouldBeTrue();
fs.File.ReadAllText(_seededPath).ShouldContain("epg_entries: 2");
(await context.ConfigElements.AnyAsync(c => c.Key == ConfigElementKey.GraphicsOnNowNextSeeded.Key)).ShouldBeTrue();
}
[Test]
public async Task Adopts_Existing_File_Untouched()
{
var fs = new MockFileSystem();
fs.Directory.CreateDirectory(FileSystemLayout.GraphicsElementsTextTemplatesFolder);
await fs.File.WriteAllTextAsync(_seededPath, "name: Operator Custom\nepg_entries: 2\n");
await using TvContext context = _db.CreateContext();
await GraphicsElementSeeder.SeedOnNowNext(context, fs, NullLogger.Instance, CancellationToken.None);
fs.File.ReadAllText(_seededPath).ShouldContain("Operator Custom");
}
[Test]
public async Task Does_Not_Resurrect_After_Delete()
{
var fs = new MockFileSystem();
await using TvContext context = _db.CreateContext();
await GraphicsElementSeeder.SeedOnNowNext(context, fs, NullLogger.Instance, CancellationToken.None);
fs.File.Delete(_seededPath);
await GraphicsElementSeeder.SeedOnNowNext(context, fs, NullLogger.Instance, CancellationToken.None);
fs.File.Exists(_seededPath).ShouldBeFalse();
}
// Guards the #570 render bugs: the seeded YAML must deserialize into a TextGraphicsElement whose
// base_style names a real style and whose every style sets a font_family — a null font_family
// crashes CustomFontMapper before its default-font fallback, so the overlay silently never renders.
[Test]
public async Task Seeded_Element_Deserializes_With_Resolvable_BaseStyle_And_Font_Families()
{
var fs = new MockFileSystem();
await using TvContext context = _db.CreateContext();
await GraphicsElementSeeder.SeedOnNowNext(context, fs, NullLogger.Instance, CancellationToken.None);
string yaml = await fs.File.ReadAllTextAsync(_seededPath);
IDeserializer deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
var element = deserializer.Deserialize<TextGraphicsElement>(yaml);
element.ShouldNotBeNull();
element.Styles.ShouldNotBeEmpty();
element.Styles.Select(s => s.Name).ShouldContain(element.BaseStyle);
element.Styles.ShouldAllBe(s => !string.IsNullOrWhiteSpace(s.FontFamily));
}
}