Files
LlamaCasty/ytLive.Tests/UiShellTests.cs
T
gramps cb4f8ec758 fix(ui): REC / ON-AIR labels are white in every state
RecordPillToggle never set a base Foreground, and its label inherits the toggle's — so unchecked
inherited the Control default (black) on the dark bar, while checked was white on red. The style
now sets on-accent once; the checked trigger only changes the fill.

That is the consistency rule for session controls: white ink always, the fill carries the state
(neutral off, red live). EDIT follows the same rule. UiShellTests asserts the base foreground, so
the missing setter cannot come back silently.
2026-10-30 10:46:51 -07:00

71 lines
4.0 KiB
C#

using System.Linq;
using Xunit;
namespace ytLive.Tests;
/// <summary>The creator's six corrections (2026-10-30) are visual rulings, so the only honest guard
/// is one that pins the ruling to the markup: if a later edit quietly reverts one of them, this
/// fails and names it.
///
/// <para>1. Stream Info + YPP rails are YouTube surfaces (YouTube red). 2. EDIT shows a real
/// off/on difference. 3. The active scene outline is orange again. 4. Scene labels wear the same
/// pill as the hotkey chips. 5. REC / ON-AIR and the running stop button read red. 6. The
/// properties list no longer caps its height, so no scrollbar appears while space remains.</para></summary>
public class UiShellTests
{
[Fact]
public void The_creators_six_ui_corrections_are_in_the_markup()
{
var preview = SourceAssert.Text("Controls", "PreviewPane.xaml");
var topBar = SourceAssert.Text("Controls", "TopBar.xaml");
var strip = SourceAssert.Text("Controls", "SceneThumbnailStrip.xaml");
var leftPanel = SourceAssert.Text("Controls", "LeftPanel.xaml");
var theme = SourceAssert.Text("Themes", "Controls.xaml");
var tokens = SourceAssert.Text("Themes", "Tokens.xaml");
// 1. YouTube-branded rails.
Assert.Contains("Brush.Youtube", tokens);
Assert.Equal(2, Count(preview, "Background=\"{StaticResource Brush.Youtube}\""));
// 2. EDIT: resting face differs from the armed face, and the label follows it.
Assert.Contains("x:Name=\"EditBody\" Background=\"{StaticResource Brush.SurfaceContainerHigh}\"", topBar);
Assert.Contains("<Setter TargetName=\"EditBody\" Property=\"Background\" Value=\"{StaticResource Brush.Tertiary}\"/>", topBar);
// The label is white in BOTH states — only the fill changes. A muted resting colour is
// what made it illegible on the dark bar (creator, 2026-10-30).
Assert.Contains("FontSize=\"12\" Foreground=\"{StaticResource Brush.OnAccent}\"", topBar);
// 3. Active scene = orange; live stays red.
Assert.Contains("IsStaged}\" Value=\"True\">\n <Setter Property=\"BorderBrush\" Value=\"{StaticResource Brush.Attention}\"/>", strip);
// 4. Scene name pill, same shape as the hotkey chip.
Assert.Contains("Padding=\"8,2\" CornerRadius=\"10\" Background=\"#000000\"", strip);
Assert.Contains("Text=\"{Binding Name, Mode=OneWay}\"", strip);
// 5. Armed session controls are red, and the running stop button is red — not a grey literal.
Assert.Contains("x:Key=\"RecordPillToggle\"", theme);
// One rule for session controls: white ink in every state, the fill carries the state.
// The missing base foreground is what painted the REC/ON-AIR labels black (2026-10-30).
var pill = theme[theme.IndexOf("x:Key=\"RecordPillToggle\"", System.StringComparison.Ordinal)..];
pill = pill[..pill.IndexOf("</Style>", System.StringComparison.Ordinal)];
Assert.Contains("<Setter Property=\"Foreground\" Value=\"{StaticResource Brush.OnAccent}\"/>", pill);
Assert.Contains("Brush.Primary", theme);
Assert.Contains("Style=\"{StaticResource RecordPillToggle}\"", topBar);
Assert.Contains("Background=\"{StaticResource Brush.Primary}\" Margin=\"14,0,0,0\"", topBar);
Assert.DoesNotContain("Background=\"#333\"", topBar);
// 6. No artificial height cap on the properties list: the list fills the row, so a
// scrollbar appears only when the content genuinely exceeds the space.
var listLine = leftPanel.Split('\n').First(line => line.Contains("ElementsScrollViewer"));
Assert.DoesNotContain("MaxHeight", listLine);
}
private static int Count(string haystack, string needle)
{
var hits = 0;
for (var i = haystack.IndexOf(needle, System.StringComparison.Ordinal); i >= 0;
i = haystack.IndexOf(needle, i + needle.Length, System.StringComparison.Ordinal))
hits++;
return hits;
}
}