using System.Reflection; using System.Xml.Linq; using OpenAC.MosswartMassacre.Views; namespace OpenAC.MosswartMassacre.Tests.Views; /// /// Every {Binding} in a markup file names a public property of the /// shape the host expects, so a typo fails here instead of as a panel that /// refuses to build in the client. /// public sealed class MarkupContractTests { public static TheoryData MarkupFiles => new() { { MainWindow.MarkupFile, typeof(MainWindow) }, }; [Theory] [MemberData(nameof(MarkupFiles))] public void EveryBindingResolvesWithTheRightShape(string file, Type bindingType) { XElement root = XDocument.Load(MarkupPath(file)).Root!; Dictionary properties = bindingType .GetProperties(BindingFlags.Public | BindingFlags.Instance) .ToDictionary(property => property.Name, StringComparer.Ordinal); foreach (XAttribute attribute in root.DescendantsAndSelf().Attributes()) { string value = attribute.Value; if (!value.StartsWith('{')) continue; Assert.Matches("^\\{[^{}]+\\}$", value); string name = value[1..^1]; Assert.True(properties.TryGetValue(name, out PropertyInfo? property), $"{file}: {value} on <{attribute.Parent!.Name}> names no public property."); string element = attribute.Parent!.Name.LocalName; Type expected = (element, attribute.Name.LocalName) switch { (_, "onclick") => typeof(Action), ("field", "onchange" or "onsubmit") => typeof(Action), ("menu", "onchange") => typeof(Action), ("list", "onchange") => typeof(Action), ("slider", "onchange") => typeof(Action), (_, "checked" or "selected" or "visible" or "enabled") when element != "list" && element != "menu" => typeof(bool), _ => typeof(object), }; if (expected != typeof(object)) Assert.True(property!.PropertyType == expected, $"{file}: {value} on <{element} {attribute.Name}> is {property.PropertyType.Name}, expected {expected.Name}."); } } [Fact] public void The_main_window_builds_its_bindings_without_a_host_ui() { using var harness = new PluginHarness(); harness.Login(); MainWindow window = harness.Feature(); Assert.Equal("Total Kills: 0", window.TotalKillsText); Assert.Equal("Meta State: Unknown", window.MetaStateText); Assert.Equal("WebSocket: [DISCONNECTED]", window.WebSocketText); Assert.Equal("Never", window.LastKillValue); window.ShowStatistics(); Assert.True(window.StatisticsSelected); Assert.False(window.MainSelected); } private static string MarkupPath(string file) => Path.Combine(AppContext.BaseDirectory, file); }