using RioJoy.Core.Overlay; using Xunit; namespace RioJoy.Core.Tests.Overlay; public class OverlayHitTesterTests { // Two stacked cells (the chroma-split overlap case) + one disjoint cell. private static OverlayTemplate Template() => new() { Width = 1000, Height = 400, Regions = { new OverlayRegion { Name = "big", X = 0, Y = 0, Width = 200, Height = 100 }, new OverlayRegion { Name = "small", X = 50, Y = 25, Width = 100, Height = 50 }, new OverlayRegion { Name = "solo", X = 500, Y = 200, Width = 80, Height = 40 }, }, }; [Fact] public void RegionsAt_ReturnsSmallestFirst() { IList hits = OverlayHitTester.RegionsAt(Template(), 100, 50); Assert.Equal(new[] { "small", "big" }, hits.Select(r => r.Name)); } [Fact] public void RegionsAt_MissReturnsEmpty() { Assert.Empty(OverlayHitTester.RegionsAt(Template(), 999, 399)); } [Fact] public void RegionsAt_EdgesAreInclusiveLeftTop_ExclusiveRightBottom() { OverlayTemplate t = Template(); Assert.Contains(OverlayHitTester.RegionsAt(t, 500, 200), r => r.Name == "solo"); Assert.Empty(OverlayHitTester.RegionsAt(t, 580, 240)); // right/bottom edge excluded } [Fact] public void NextAt_FirstClickSelectsSmallest() { OverlayRegion? hit = OverlayHitTester.NextAt(Template(), 100, 50, currentName: null); Assert.Equal("small", hit?.Name); } [Fact] public void NextAt_CyclesThroughStackAndWraps() { OverlayTemplate t = Template(); Assert.Equal("big", OverlayHitTester.NextAt(t, 100, 50, "small")?.Name); Assert.Equal("small", OverlayHitTester.NextAt(t, 100, 50, "big")?.Name); // wrap Assert.Equal("small", OverlayHitTester.NextAt(t, 100, 50, "SOLO")?.Name); // current not in stack } [Fact] public void NextAt_CurrentNameIsCaseInsensitive() { Assert.Equal("big", OverlayHitTester.NextAt(Template(), 100, 50, "SMALL")?.Name); } [Fact] public void NextAt_MissReturnsNull() { Assert.Null(OverlayHitTester.NextAt(Template(), 5, 395, "small")); } }