using System.IO; using System.Linq; using System.Xml.Linq; using Xunit; namespace ytLive.Tests; /// TASK 58 — the creator's style audit (2026-10-21): "in the Live scene, for the /// layer Stream Alerts, the properties → display — why is the drop-down box not in the same /// style as the others?" It was never given the theme's YtComboBox style — only a /// hand-painted Background/Foreground — so WPF fell back to the light system template, and /// the chat Font drop-down (copied from it) was the same. The sweep found the same smell in /// every check box and every properties field. /// /// This test is the guard: every drop-down and check box in the app carries the theme's /// style, and every field in the properties panel carries the compact theme style and paints /// no colour of its own — the theme owns the look, so it cannot drift back. public class PropertiesStyleTests { private static readonly XNamespace Xaml = "http://schemas.microsoft.com/winfx/2006/xaml"; [Fact] public void Every_drop_down_check_box_and_properties_field_carries_the_theme_style() { // 1. The theme defines the styles the app relies on. var theme = XDocument.Load(SourceAssert.RepoPath("Themes", "Controls.xaml")); var keys = theme.Descendants() .Where(e => e.Name.LocalName == "Style") .Select(e => (string?)e.Attribute(Xaml + "Key")) .Where(k => k != null) .ToHashSet(); foreach (var required in new[] { "YtComboBox", "YtCheckBox", "YtTextBox", "YtTextBoxCompact" }) Assert.Contains(required, keys); // 2. Every drop-down and check box in the app carries the theme style — an unstyled // one falls back to the light WPF system template. foreach (var file in AppXamlFiles()) { var doc = XDocument.Load(file); var where = Path.GetFileName(file); foreach (var combo in doc.Descendants().Where(e => e.Name.LocalName == "ComboBox")) AssertStyled(combo, "YtComboBox", $"{where}: a ComboBox is not styled with YtComboBox — it renders with the light system template"); // Every check box is a pill switch (creator ruling, 2026-11-01: "all checkboxes as // pill switches"), so PropertyPillCheck is the theme style that matters here; YtCheckBox // is still accepted where a plain box is deliberate. foreach (var check in doc.Descendants().Where(e => e.Name.LocalName == "CheckBox")) { var style = (string?)check.Attribute("Style") ?? string.Empty; Assert.True( style.Contains("PropertyPillCheck", StringComparison.Ordinal) || style.Contains("YtCheckBox", StringComparison.Ordinal), $"{where}: a CheckBox carries no theme style — it renders with the light system template"); } } // 3. Every field in the properties panel carries the compact theme style and paints // no colours of its own. var left = XDocument.Load(SourceAssert.RepoPath("Controls", "LeftPanel.xaml")); var properties = left.Descendants().Single(e => e.Name.LocalName == "StackPanel" && (string?)e.Attribute(Xaml + "Name") == "ElementsPanel"); var fields = properties.Descendants().Where(e => e.Name.LocalName == "TextBox").ToList(); Assert.NotEmpty(fields); foreach (var box in fields) { AssertStyled(box, "YtTextBoxCompact", "a properties field is not styled with YtTextBoxCompact"); Assert.Null(box.Attribute("Background")); Assert.Null(box.Attribute("BorderBrush")); } } /// The app's XAML: the windows at the repo root plus the carved-up controls. private static string[] AppXamlFiles() { var root = Path.GetDirectoryName(SourceAssert.RepoPath("ytLive.csproj"))!; return Directory.GetFiles(root, "*.xaml", SearchOption.TopDirectoryOnly) .Concat(Directory.GetFiles(Path.Combine(root, "Controls"), "*.xaml", SearchOption.TopDirectoryOnly)) .OrderBy(f => f) .ToArray(); } /// Asserts the element carries the named theme style. private static void AssertStyled(XElement element, string key, string message) { var style = (string?)element.Attribute("Style"); Assert.True(style is not null && style.Contains(key, StringComparison.Ordinal), message); } }