using System; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Controls; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; [Collection("RealApp")] public sealed class TextLayerEditorPreviewTests { private readonly RealAppHost _app; public TextLayerEditorPreviewTests(RealAppHost app) => _app = app; [Fact] public void Editing_One_Text_Layer_Updates_Only_That_Preview() { _app.Run(Run); } private static void Run() { var dbPath = Path.Combine(Path.GetTempPath(), $"ytLlive-text-editor-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = dbPath; MainWindow? window = null; try { window = new MainWindow(); var vm = (MainViewModel)window.DataContext; vm.EditingActive = true; vm.StagedScene = vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Live)); vm.AddSourceCommand.Execute(SourceType.TextOverlay); vm.AddSourceCommand.Execute(SourceType.TextOverlay); var textLayers = vm.StagedScene!.Elements.OfType() .Where(source => source.Type == SourceType.TextOverlay).ToArray(); Assert.Equal(2, textLayers.Length); var first = textLayers[0]; var second = textLayers[1]; second.TextContent = "Leave this caption alone"; vm.SelectedElement = first; window.Show(); window.UpdateLayout(); var leftPanel = (LeftPanel)window.FindName("LeftPanel")!; var editor = (TextBox)leftPanel.FindName("TextLayerEditor")!; Assert.Equal("Text", editor.Text); Assert.True(first.IsDraggable); Assert.Equal(900, first.Width); Assert.Equal(140, first.Height); editor.Text = "Updated headline\nSecond line"; editor.GetBindingExpression(TextBox.TextProperty)?.UpdateSource(); window.UpdateLayout(); Assert.Equal("Updated headline\nSecond line", first.TextContent); Assert.Equal("Leave this caption alone", second.TextContent); var preview = (PreviewPane)window.FindName("PreviewPane")!; var firstPreview = FindTextPreview(preview, first); var secondPreview = FindTextPreview(preview, second); Assert.NotNull(firstPreview); Assert.NotNull(secondPreview); Assert.Equal("Updated headline\nSecond line", firstPreview!.Text); Assert.Equal("Leave this caption alone", secondPreview!.Text); Assert.True(firstPreview.IsVisible); Assert.True(secondPreview.IsVisible); } finally { window?.Close(); MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { File.Delete(dbPath); } catch { /* best-effort cleanup */ } } } private static TextBlock? FindTextPreview(DependencyObject parent, Source source) { if (parent is TextBlock text && Equals(text.Tag, "TextLayerPreview") && ReferenceEquals(text.DataContext, source)) return text; for (var i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var result = FindTextPreview(VisualTreeHelper.GetChild(parent, i), source); if (result != null) return result; } return null; } }