The earlier pass checked wiring only; this is the typography sweep. Raw Foreground/FontSize labels are gone from the elements panel: - Opacity, Timer (minutes) and URI are headings above their control (PropertyHeader), with the control row on the panel's 10px indent — the same shape as Border Thickness/Opacity. - Scroll speed, scoreboard Opacity/Text size and their value readouts are PropertyFieldLabel. - The drag hint and the scoreboard sign-in note are PropertyHint. - Simulate (dev) keeps its orange, gains the field-label typography. - Edge, Text colour and Background were PropertySubHeader/SubHeader: ONE heading rank now, so PropertySubHeader and the legacy SubHeader are deleted from Themes/Controls.xaml. - DeveloperPanel — the last panel with raw typography and an unstyled CheckBox — now uses the same styles, and PropertiesStyleTests accepts PropertyPillCheck (the guard went stale when every check box became a pill switch). 18 tests pass; Release 0 warnings.
93 lines
4.5 KiB
C#
93 lines
4.5 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
using Xunit;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
/// <summary>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 <c>YtComboBox</c> 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.
|
|
///
|
|
/// <para>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.</para></summary>
|
|
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"));
|
|
}
|
|
}
|
|
|
|
/// <summary>The app's XAML: the windows at the repo root plus the carved-up controls.</summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>Asserts the element carries the named theme style.</summary>
|
|
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);
|
|
}
|
|
}
|