using System; using System.Collections.Generic; using System.Threading; using Xunit; using ytLive.Services; using ytLive.Services.Compositor; namespace ytLive.Tests; /// The strip is state, not events: everything enabled is always on screen. These checks /// paint the real frame, because a renderer that silently draws nothing would still pass a /// structural test. public class ScoreboardRendererTests { private static readonly List Tiles = new() { "Members 12", "Milestones 3", "SC $47.00" }; [Fact] public void The_strip_paints_the_plate_and_the_text_and_never_needs_a_scroll() { Exception? failure = null; var thread = new Thread(() => { try { // Plate on: half-transparent blue behind white text. var plated = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", true, "#0000FF", 0.5)); Assert.NotNull(plated); Assert.Equal(ScoreboardRenderer.Width, plated!.Width); Assert.True(plated.Height > 0); Assert.True(Count(plated, (r, g, b, a) => b > 150 && r < 60 && g < 60 && a is > 100 and < 170) > 500, "the plate must fill at the chosen colour and opacity"); Assert.True(Count(plated, (r, g, b, a) => r > 200 && g > 200 && b > 200 && a > 200) > 20, "the text must be painted in the chosen colour"); // Plate off: the same area is transparent, the text survives. var bare = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", false, "#0000FF", 0.5)); Assert.NotNull(bare); Assert.Equal(0, Count(bare!, (r, g, b, a) => b > 150 && r < 60 && g < 60 && a > 100)); Assert.True(Count(bare!, (r, g, b, a) => r > 200 && g > 200 && b > 200 && a > 200) > 20); // Text colour reaches the glyphs. var red = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FF0000", false, "#000000", 0.5)); Assert.True(Count(red!, (r, g, b, a) => r > 180 && g < 80 && b < 80 && a > 200) > 20); // Nothing enabled: no frame at all (the layer draws nothing). Assert.Null(ScoreboardRenderer.Render(Array.Empty(), new ScoreboardStyle())); } catch (Exception ex) { failure = ex; } }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); Assert.Null(failure); } private static int Count(VideoFrame frame, Func predicate) { var hits = 0; for (var i = 0; i < frame.BgraPixels.Length; i += 4) if (predicate(frame.BgraPixels[i + 2], frame.BgraPixels[i + 1], frame.BgraPixels[i], frame.BgraPixels[i + 3])) hits++; return hits; } }