Build 729 (creator): - "press <esc> to return" loses the word "press"; the label is "Record / Go-Live". - The bar takes focus on "Build scenes" and Tab cycles between the two halves only (KeyboardNavigation.TabNavigation="Cycle"), never off into the window. - Entering Record / Go-Live starts with NOTHING chosen — the output switches are a fresh decision, not a remembered one. - Three states: nothing chosen [YouTube][Local MP4]; YouTube chosen [YouTube(red)][Live Stream][Private Stream]; Local MP4 chosen [Local MP4(red)][Start Recording] → [End Recording] while recording. Only the chosen output is red; the action chips never highlight. Choosing Local MP4 takes the left slot and the YouTube chip disappears with it, which is what "slides to the left, replacing it" describes. "Private Stream" is the private-visibility stream — the same thing this app has always called the test stream (creator's clarification, so the wording is deliberate, not a new broadcast type). Output chips are one style with a Tag-driven trigger (OutputChip + OutputChipIcon), so a chip's red face and its glyph colour can't drift apart; the one-alpha hit-area colour is a token, because DesignTokensTests rightly refuses literals in theme files. 680 pass, 0 warnings. Scope justification: Assets/starting-background.jpg is outside this unit — the creator's replacement art, still awaiting their visual check.
121 lines
4.6 KiB
C#
121 lines
4.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using Xunit;
|
|
using ytLive.ViewModels;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
/// <summary>
|
|
/// The top bar's one decision: <c>[ Build Scenes ][ Record / Go Live ]</c>. Build Scenes ships
|
|
/// highlighted, and it <b>is</b> edit mode — the old EDIT toggle is gone, so "can I edit?" and "which
|
|
/// world am I in?" cannot disagree.
|
|
/// </summary>
|
|
[Collection("MainViewModelLayoutPath")]
|
|
public class TopBarWorldTests
|
|
{
|
|
[Fact]
|
|
public void The_output_stage_belongs_to_the_output_world_and_holds_one_output_at_a_time()
|
|
{
|
|
var db = Path.Combine(Path.GetTempPath(), $"llamacasty-outputstage-{Guid.NewGuid():N}.db");
|
|
MainViewModel.LayoutPathOverride = db;
|
|
try
|
|
{
|
|
var vm = new MainViewModel();
|
|
|
|
// Nothing to arm while building scenes.
|
|
Assert.False(vm.ShowOutputStage);
|
|
|
|
vm.EnterOutputWorldCommand.Execute(null);
|
|
Assert.True(vm.IsOutputWorld);
|
|
Assert.True(vm.IsOffline);
|
|
Assert.False(vm.IsRecording);
|
|
Assert.True(vm.ShowOutputStage);
|
|
|
|
// Entering the output world starts with NOTHING chosen (creator, build 729); the pair is
|
|
// one axis, so arming either drops the other.
|
|
Assert.False(vm.RecordPillOn);
|
|
Assert.False(vm.OnAirPillOn);
|
|
vm.OnAirPillOn = true;
|
|
Assert.True(vm.OnAirPillOn);
|
|
Assert.False(vm.RecordPillOn);
|
|
vm.RecordPillOn = true;
|
|
Assert.False(vm.OnAirPillOn);
|
|
vm.RecordPillOn = false; // back to "nothing chosen" for the state checks below
|
|
|
|
// Nothing chosen yet: both output chips, no action.
|
|
Assert.True(vm.ShowOutputChoice);
|
|
Assert.False(vm.ShowYouTubeSelected);
|
|
Assert.False(vm.ShowLocalMp4Selected);
|
|
Assert.True(vm.YouTubeChipVisible);
|
|
Assert.True(vm.LocalMp4ChipVisible);
|
|
|
|
// YouTube chosen: its chip stays (red), two actions appear, MP4's chip goes away.
|
|
vm.SelectYouTubeCommand.Execute(null);
|
|
Assert.True(vm.ShowYouTubeSelected);
|
|
Assert.False(vm.ShowOutputChoice);
|
|
Assert.True(vm.YouTubeChipVisible);
|
|
Assert.False(vm.LocalMp4ChipVisible);
|
|
|
|
// Local MP4 chosen: it takes the left slot, one action, and Start/End swap on recording.
|
|
vm.SelectLocalMp4Command.Execute(null);
|
|
Assert.True(vm.ShowLocalMp4Selected);
|
|
Assert.False(vm.YouTubeChipVisible);
|
|
Assert.True(vm.LocalMp4ChipVisible);
|
|
Assert.True(vm.ShowStartRecordingAction);
|
|
Assert.False(vm.ShowEndRecordingAction);
|
|
|
|
// Neither action exists while building scenes.
|
|
vm.EnterBuildWorldCommand.Execute(null);
|
|
Assert.False(vm.ShowStartRecordingAction);
|
|
Assert.False(vm.ShowEndRecordingAction);
|
|
Assert.False(vm.YouTubeChipVisible);
|
|
Assert.False(vm.LocalMp4ChipVisible);
|
|
}
|
|
finally
|
|
{
|
|
MainViewModel.LayoutPathOverride = null;
|
|
try { File.Delete(db); } catch (IOException) { }
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Build_scenes_is_the_default_world_and_is_the_only_place_editing_lives()
|
|
{
|
|
var db = Path.Combine(Path.GetTempPath(), $"llamacasty-world-{Guid.NewGuid():N}.db");
|
|
MainViewModel.LayoutPathOverride = db;
|
|
try
|
|
{
|
|
var vm = new MainViewModel();
|
|
|
|
// Launch state: Build Scenes highlighted, editing on.
|
|
Assert.Equal(BarWorld.Build, vm.BarWorld);
|
|
Assert.True(vm.IsBuildWorld);
|
|
Assert.False(vm.IsOutputWorld);
|
|
Assert.True(vm.IsEditMode);
|
|
|
|
// Record / Go Live leaves edit mode — the output surface has nothing to drag.
|
|
vm.EnterOutputWorldCommand.Execute(null);
|
|
Assert.Equal(BarWorld.Output, vm.BarWorld);
|
|
Assert.True(vm.IsOutputWorld);
|
|
Assert.False(vm.IsBuildWorld);
|
|
Assert.False(vm.IsEditMode);
|
|
|
|
// Clicking the highlighted half is not a no-op: it re-enters that world, which is how a
|
|
// creator takes editing back during a session.
|
|
vm.EnterBuildWorldCommand.Execute(null);
|
|
Assert.True(vm.IsBuildWorld);
|
|
Assert.True(vm.IsEditMode);
|
|
|
|
// …and re-entering the world already in force still re-asserts its edit state.
|
|
vm.EditingActive = false;
|
|
vm.EnterBuildWorldCommand.Execute(null);
|
|
Assert.True(vm.IsEditMode);
|
|
}
|
|
finally
|
|
{
|
|
MainViewModel.LayoutPathOverride = null;
|
|
try { File.Delete(db); } catch (IOException) { }
|
|
}
|
|
}
|
|
}
|