using System.Reflection; using AcDream.App.Rendering; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using Xunit; namespace AcDream.App.Tests.Rendering; /// /// The icon resource names are coupled to LogicalName in /// AcDream.App.csproj by string alone, so a rename on either side compiles /// cleanly and only fails as a silently icon-less window at runtime. These /// tests are that coupling's only guard. /// public class WindowIconLoaderTests { private static IReadOnlyList ExpectedResourceNames() { var field = typeof(WindowIconLoader).GetField( "ResourceNames", BindingFlags.NonPublic | BindingFlags.Static); Assert.NotNull(field); var names = (string[]?)field!.GetValue(null); Assert.NotNull(names); return names!; } [Fact] public void EveryDeclaredIconResource_IsActuallyEmbedded() { var assembly = typeof(WindowIconLoader).Assembly; string[] embedded = assembly.GetManifestResourceNames(); foreach (string name in ExpectedResourceNames()) { Assert.True( embedded.Contains(name), $"WindowIconLoader expects embedded resource '{name}', but the " + "assembly does not contain it. Check the EmbeddedResource " + "LogicalName entries in AcDream.App.csproj."); } } [Fact] public void EmbeddedIcons_DecodeToSquareRgbaImagesOfTheDeclaredSize() { var assembly = typeof(WindowIconLoader).Assembly; foreach (string name in ExpectedResourceNames()) { using Stream? stream = assembly.GetManifestResourceStream(name); Assert.NotNull(stream); using var image = Image.Load(stream!); Assert.Equal(image.Width, image.Height); // The trailing "-.png" must match the actual pixel size, or // the window manager picks the wrong image for a surface. string stem = Path.GetFileNameWithoutExtension(name); string declared = stem[(stem.LastIndexOf('-') + 1)..]; Assert.Equal(int.Parse(declared), image.Width); } } [Fact] public void IconSet_CoversBothSmallAndLargeSurfaces() { var sizes = new List(); foreach (string name in ExpectedResourceNames()) { string stem = Path.GetFileNameWithoutExtension(name); sizes.Add(int.Parse(stem[(stem.LastIndexOf('-') + 1)..])); } // Title bars want ~16px and Alt-Tab/taskbar want a large one; shipping // only one size leaves the window manager resampling badly. Assert.Contains(16, sizes); Assert.True(sizes.Max() >= 128, "icon set has no large size for Alt-Tab/taskbar"); } }