Unit A of the top-bar redesign (creator ruling 2026-11-12). The standalone EDIT toggle is gone; Build Scenes IS edit mode, so "which world am I in?" and "can I edit?" cannot disagree any more. BarWorld (ViewModels/MainViewModel.TopBar.cs) has two values, Build and Output. Build ships highlighted at launch and sets EditingActive on; choosing Record / Go Live turns it off. Clicking the already-highlighted half is deliberately not a no-op: it re-enters that world, which is the only way back to the layers during a session now that the EDIT button is gone (unit 1 made that legal). WorldSegmentButton (Themes/Controls.xaml) is a Button, not a ToggleButton, and each half passes its own flag through Tag to one shared DataTrigger — a ToggleButton would fight the view model and, with a one-way IsChecked, clear its own binding on first click. UiShellTests updated where it guarded the old EDIT markup (it now guards the segment). TopBarWorldTests pins launch state, both transitions, and the re-enter case. 679 pass, 0 warnings. Next: unit B (output switch), unit C (output-dependent action + End labels). Scope justification: Assets/starting-background.jpg is outside this unit — the creator's replacement art, still awaiting their visual check.
112 lines
6.3 KiB
C#
112 lines
6.3 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. The world segment replaced the EDIT toggle (creator ruling 2026-11-12): both halves are
|
|
// present, each lit by its own world flag through the shared style.
|
|
Assert.Contains("Content=\"Build Scenes\"", topBar);
|
|
Assert.Contains("Content=\"Record / Go Live\"", topBar);
|
|
Assert.Contains("Tag=\"{Binding IsBuildWorld}\"", topBar);
|
|
Assert.Contains("Tag=\"{Binding IsOutputWorld}\"", topBar);
|
|
Assert.DoesNotContain("x:Name=\"EditBody\"", 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);
|
|
}
|
|
|
|
[Fact]
|
|
public void The_wordmark_ty_stays_youtube_red_and_ctrl_opens_the_context_menu()
|
|
{
|
|
var topBar = SourceAssert.Text("Controls", "TopBar.xaml");
|
|
// Adjacent, with nothing between: whitespace inside a TextBlock between inline Runs
|
|
// collapses to a space and prints "LlamaCas ty" (this exact bug shipped once).
|
|
Assert.Contains("<Run Text=\"LlamaCas\" Foreground=\"{StaticResource Brush.OnSurface}\"/><Run Text=\"ty\" Foreground=\"{StaticResource Brush.Youtube}\"/>", topBar);
|
|
|
|
// Plain right-click is the zoom box; the context menu moved to Ctrl+right-click so a
|
|
// creator can change capture sources mid-stream.
|
|
var preview = SourceAssert.Text("Controls", "PreviewPane.xaml.cs");
|
|
Assert.Contains("ModifierKeys.Control", preview);
|
|
Assert.Contains("return;", preview);
|
|
}
|
|
|
|
[Fact]
|
|
public void Settings_gear_is_orange_on_the_preview_rail_and_EDIT_precedes_the_session_cluster()
|
|
{
|
|
var topBar = SourceAssert.Text("Controls", "TopBar.xaml");
|
|
var preview = SourceAssert.Text("Controls", "PreviewPane.xaml");
|
|
|
|
// The settings gear moved from the top bar to the first orange preview-rail tab.
|
|
var settingsTooltip = preview.IndexOf("ToolTip=\"Settings\"", System.StringComparison.Ordinal);
|
|
Assert.True(settingsTooltip >= 0, "the Settings gear tab is missing from the preview rail");
|
|
var gearStart = preview.LastIndexOf("<Border ", settingsTooltip, System.StringComparison.Ordinal);
|
|
var gearEnd = preview.IndexOf("</Border>", settingsTooltip, System.StringComparison.Ordinal);
|
|
Assert.True(gearStart >= 0 && gearEnd > settingsTooltip, "the Settings tab has no bordered gear surface");
|
|
var gear = preview[gearStart..gearEnd];
|
|
Assert.Contains("Background=\"{StaticResource Brush.Attention}\"", gear);
|
|
Assert.Contains("MouseLeftButtonUp=\"SettingsTab_Click\"", gear);
|
|
Assert.DoesNotContain("ToolTip=\"Settings\"", topBar);
|
|
|
|
// The world segment leads the centre cluster; the brand column carries no edit control.
|
|
var centre = topBar.IndexOf("<StackPanel Grid.Column=\"1\"", System.StringComparison.Ordinal);
|
|
var segment = topBar.IndexOf("Content=\"Build Scenes\"", System.StringComparison.Ordinal);
|
|
Assert.True(centre > 0 && segment > centre,
|
|
"the [ Build Scenes ][ Record / Go Live ] segment must lead the centre cluster");
|
|
Assert.DoesNotContain("x:Name=\"EditBody\"", topBar);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|