Files
LlamaCasty/ytLive.Tests/OnAirSignTests.cs
T
gramps ec01a7deb8 design: the last VM-side colours come from tokens (ThemeBrush)
The state colours the view-models hand to bindings — top bar, REC/ON-AIR dots, health banner,
meter bands, toast tints — were hex literals in C#. They now resolve from Themes/Tokens.xaml
through `Helpers/ThemeBrush`, so the values live in one place. Without an Application (unit tests)
the helper returns a neutral grey: visibly wrong rather than silently plausible.

Four tokens the code needed and the document lacked, added to DESIGN.md (so the doc-is-the-contract
guard demanded their brushes): info-container #3a3b52, success-container #1d5c38,
warning-container #b8860b, test-container #9c6f1c (the test-stream gold bar).

Also fixed by this: the top bar still painted the RETIRED brand red #e94560 when live — the
standard's #ff5451 now, and `OnAirSignTests` (which pinned the old value) says so. BarOn/BarOff
became properties rather than static fields, because a static field would resolve tokens before
the Application exists.

Verified: DesignTokensTests, GameMeterHonestyTests, NotificationAreaIntegrationTests,
OnAirSignTests, SessionTeardownTests — 38 tests green.
2026-10-30 09:58:52 -07:00

64 lines
1.9 KiB
C#

using System;
using System.ComponentModel;
using Xunit;
using ytLive.Models;
using ytLive.ViewModels;
namespace ytLive.Tests;
/// <summary>
/// The ON-AIR sign (right of REC in the top bar): gray offline, red when
/// streaming public, green when streaming private. Driven through the real
/// MainViewModel so StreamStatus/StreamVisibility notification wiring is
/// exercised, not just the computed property.
/// </summary>
[Collection("RealApp")]
public sealed class OnAirSignTests
{
[Fact]
public void OnAirBrush_Follows_Offline_Public_And_Private()
{
_app.Run(Run);
}
private readonly RealAppHost _app;
public OnAirSignTests(RealAppHost app) => _app = app;
private void Run()
{
var tempDb = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"ytLlive-onair-{Guid.NewGuid():N}.db");
MainViewModel.LayoutPathOverride = tempDb;
try
{
using (var schema = new ytLive.Services.LayoutStore(tempDb)) { }
Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools();
var vm = new MainViewModel();
Assert.Equal(StreamStatus.Offline, vm.StreamStatus);
Assert.Equal("#5b6478", vm.OnAirBrush);
var raised = 0;
vm.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(MainViewModel.OnAirBrush)) raised++; };
vm.StreamVisibility = "Public";
Assert.Equal("#5b6478", vm.OnAirBrush);
vm.StreamStatus = StreamStatus.Streaming;
Assert.Equal("#ff5451", vm.OnAirBrush);
vm.StreamVisibility = "Private";
Assert.Equal("#22c55e", vm.OnAirBrush);
Assert.Equal(3, raised);
}
finally
{
MainViewModel.LayoutPathOverride = null;
Microsoft.Data.Sqlite.SqliteConnection.ClearAllPools();
try { System.IO.File.Delete(tempDb); } catch { /* best-effort cleanup */ }
}
}
}