using System; using System.Linq; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; /// /// Duplicate source names get an incrementing suffix with no space (Image, /// Image2, Image3…) and the next free number is derived from the names actually /// in the scene — deleting a middle resource never collides with a survivor. /// Drives the real VM through the Add Source command (TextOverlay needs no /// dialog), the same real-App + temp-DB pattern as the round-clip test. /// [Collection("RealApp")] public sealed class SourceNamingTests { private readonly RealAppHost _app; public SourceNamingTests(RealAppHost app) { _app = app; } [Fact] public void Duplicate_Sources_Get_Next_Free_Numbered_Name() { _app.Run(Run); } private void Run() { var tempDb = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"ytLlive-srcname-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; var window = new MainWindow(); var vm = (MainViewModel)window.DataContext; try { var scene = vm.ActiveScene!; vm.AddSourceCommand.Execute(SourceType.TextOverlay); vm.AddSourceCommand.Execute(SourceType.TextOverlay); vm.AddSourceCommand.Execute(SourceType.TextOverlay); var names = scene.Elements.OfType().Select(s => s.Name).ToList(); Assert.Equal(new[] { "Text", "Text2", "Text3" }, names); var middle = scene.Elements.OfType().Single(s => s.Name == "Text2"); scene.Elements.Remove(middle); vm.AddSourceCommand.Execute(SourceType.TextOverlay); var survivors = scene.Elements.OfType().Select(s => s.Name).ToList(); Assert.Equal(new[] { "Text", "Text3", "Text2" }, survivors); } finally { window.Close(); MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { System.IO.File.Delete(tempDb); } catch { /* best-effort cleanup */ } } } }