Unit C (creator ruling 2026-11-12). - Local MP4: one button, "Start Recording". - YouTube: "Private Test Stream" beside "Review & Go Live", the latter with the primary face because it is the default ask. - Running: "End Live Stream" (or "End Test" for a test run, "Stop Recording" for a local one). The behavioural change underneath: SessionStartDecision.For no longer takes `editing`. Since 2026-10-30 EDIT silently chose test-vs-real, which meant the same button did two different things depending on a toggle three inches away. With Test as its own button that inference has no job, so For() now reads only the armed output and ON-AIR always means the real livestream. That supersedes the 2026-10-30 ruling; SessionStartDecisionTests is rewritten to pin the new matrix rather than the old one. A signed-out press still starts the sign-in flow instead of sitting dead (no-dead-ends), unchanged from before — now stated in one place, the two new commands, instead of inside a route table. 680 pass, 0 warnings. Scope justification: Assets/starting-background.jpg is outside this unit — the creator's replacement art, still awaiting their visual check.
102 lines
3.7 KiB
C#
102 lines
3.7 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);
|
|
|
|
// Local MP4 is the default output; the pair is one axis, so arming either drops the other.
|
|
Assert.True(vm.RecordPillOn);
|
|
Assert.False(vm.OnAirPillOn);
|
|
vm.OnAirPillOn = true;
|
|
Assert.True(vm.OnAirPillOn);
|
|
Assert.False(vm.RecordPillOn);
|
|
vm.RecordPillOn = true;
|
|
Assert.False(vm.OnAirPillOn);
|
|
|
|
// The action follows the output: one button for MP4, two for YouTube (test + real).
|
|
Assert.True(vm.ShowStartRecordingAction);
|
|
Assert.False(vm.ShowYouTubeStartActions);
|
|
vm.OnAirPillOn = true;
|
|
Assert.False(vm.ShowStartRecordingAction);
|
|
Assert.True(vm.ShowYouTubeStartActions);
|
|
|
|
// Neither action exists while building scenes.
|
|
vm.EnterBuildWorldCommand.Execute(null);
|
|
Assert.False(vm.ShowStartRecordingAction);
|
|
Assert.False(vm.ShowYouTubeStartActions);
|
|
}
|
|
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) { }
|
|
}
|
|
}
|
|
}
|