using System; using System.IO; using System.Linq; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; /// /// TASK 65 slice 5 — the replay layer as a thing the creator can add, and the one guard that matters. /// /// The layer is an ordinary media layer with an app-owned path, so the test only has to prove the /// flags: one per scene, silent by default, once-through in Live and looping everywhere else. Playback /// itself rides the media manager that TASK 21 already covers. /// [Collection("RealApp")] public sealed class ReplayLayerTests { private readonly RealAppHost _app; public ReplayLayerTests(RealAppHost app) => _app = app; [Fact] public void AddReplayLayer_IsOnePerScene_SilentByDefault_AndLoopsOutsideLive() => _app.Run(() => { var tempDb = Path.Combine(Path.GetTempPath(), $"ytLlive-replay-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; try { var vm = new MainViewModel(); vm.StagedScene = vm.Scenes.Single(s => SceneCatalog.Is(s.Name, SceneCatalog.Live)); vm.AddReplayLayer(); vm.AddReplayLayer(); // second add is a no-op var layers = vm.Scenes.SelectMany(s => s.Elements).OfType() .Where(s => s.IsReplayLayer).ToList(); Assert.Single(layers); var liveLayer = layers[0]; Assert.True(liveLayer.MediaMuted); // silent by default Assert.False(liveLayer.MediaIsLooping); // Live plays once // Any other scene loops the kept set. vm.StagedScene = vm.Scenes.Single(s => SceneCatalog.Is(s.Name, SceneCatalog.Brb)); vm.AddReplayLayer(); var brbLayer = vm.Scenes.SelectMany(s => s.Elements).OfType() .Single(s => s.IsReplayLayer && s != liveLayer); Assert.True(brbLayer.MediaIsLooping); Assert.True(brbLayer.MediaMuted); // Clips off by default, and with no ring nothing is written by a stray F10. Assert.False(vm.ClipsEnabled); vm.SaveReplayClip(); var clipsFolder = Path.Combine(Path.GetDirectoryName(tempDb)!, "clips"); Assert.False(Directory.Exists(clipsFolder) && Directory.EnumerateFiles(clipsFolder).Any()); } finally { MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { File.Delete(tempDb); } catch { /* best effort */ } } }); }