using System; using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Controls; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; [Collection("RealApp")] public sealed class TextLayerDropdownTests { private readonly RealAppHost _app; public TextLayerDropdownTests(RealAppHost app) => _app = app; [Fact] public void Text_Controls_Show_Defaults_Update_And_Restore_Selected_Values() { _app.Run(Run); } private static void Run() { var dbPath = Path.Combine(Path.GetTempPath(), $"ytLlive-text-controls-{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); var source = vm.StagedScene!.Elements.OfType() .Single(item => item.Type == SourceType.TextOverlay); vm.SelectedElement = source; window.Show(); window.UpdateLayout(); var panel = (LeftPanel)window.FindName("LeftPanel")!; var fontType = (ComboBox)panel.FindName("TextLayerFontTypePicker")!; var font = (ComboBox)panel.FindName("TextLayerFontPicker")!; var size = (ComboBox)panel.FindName("TextLayerSizePicker")!; var colorField = (TextBox)panel.FindName("TextLayerColorEditor")!; var color = (ComboBox)panel.FindName("TextLayerColorPicker")!; var horizontal = (ComboBox)panel.FindName("TextLayerHorizontalAlignmentPicker")!; var vertical = (ComboBox)panel.FindName("TextLayerVerticalAlignmentPicker")!; Assert.Equal("Sans Serif", fontType.SelectedItem); Assert.Equal("Sans Serif", fontType.Text); Assert.Equal("Segoe UI", font.SelectedItem); Assert.Equal("Segoe UI", font.Text); Assert.Equal(48d, size.SelectedItem); Assert.Equal("48", size.Text); Assert.Equal("#FFFFFF", colorField.Text); Assert.Equal(source.TextColorEntry, color.SelectedItem); Assert.Equal(TextLayerAlignment.Left, horizontal.SelectedItem); Assert.Equal("Left", horizontal.Text); Assert.Equal(TextLayerVerticalAlignment.Top, vertical.SelectedItem); Assert.Equal("Top", vertical.Text); Assert.Same(Application.Current.Resources["YtComboBox"], color.Style); Assert.Same(panel.Resources["BorderColorTemplates"], color.ItemTemplateSelector); Assert.Equal(10, ((FrameworkElement)fontType.Parent).Margin.Left); Assert.Equal(10, ((FrameworkElement)color.Parent).Margin.Left); Assert.Equal(10, ((FrameworkElement)horizontal.Parent).Margin.Left); Assert.Equal(10, ((FrameworkElement)vertical.Parent).Margin.Left); fontType.SelectedItem = "Serif"; window.UpdateLayout(); Assert.Equal("Serif", vm.SelectedTextFontType); Assert.Equal("Segoe UI", source.TextFontFamily); Assert.NotEmpty(font.Items); var serifFont = font.Items.Cast().First(); font.SelectedItem = serifFont; size.SelectedItem = 36d; color.SelectedItem = source.TextColorOptions.Single(item => item.Hex == "#FF0000"); horizontal.SelectedItem = TextLayerAlignment.Center; vertical.SelectedItem = TextLayerVerticalAlignment.Bottom; window.UpdateLayout(); Assert.Equal(serifFont, source.TextFontFamily); Assert.Equal(36, source.TextFontSize); Assert.Equal("#FF0000", source.TextColor); Assert.Equal(TextLayerAlignment.Center, source.TextAlignment); Assert.Equal(TextLayerVerticalAlignment.Bottom, source.TextVerticalAlignment); var raster = Assert.IsType(vm.ResolveOutputFrame(source)); Assert.True(FirstInkRow(raster) > 50, "bottom alignment did not place the text lower inside its box"); Assert.Equal("Serif", fontType.SelectedItem); Assert.Equal(serifFont, font.SelectedItem); Assert.Equal(serifFont, font.Text); Assert.Equal(36d, size.SelectedItem); Assert.Equal("36", size.Text); Assert.Equal("#FF0000", colorField.Text); Assert.Equal(source.TextColorEntry, color.SelectedItem); Assert.Equal(TextLayerAlignment.Center, horizontal.SelectedItem); Assert.Equal("Center", horizontal.Text); Assert.Equal(TextLayerVerticalAlignment.Bottom, vertical.SelectedItem); Assert.Equal("Bottom", vertical.Text); vm.SaveLayoutNow(); window.Close(); window = null; SqliteConnection.ClearAllPools(); window = new MainWindow(); var reloadedVm = (MainViewModel)window.DataContext; reloadedVm.EditingActive = true; reloadedVm.StagedScene = reloadedVm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Live)); var reloaded = reloadedVm.StagedScene.Elements.OfType() .Single(item => item.Type == SourceType.TextOverlay); reloadedVm.SelectedElement = reloaded; window.Show(); window.UpdateLayout(); var reloadedPanel = (LeftPanel)window.FindName("LeftPanel")!; Assert.Equal(reloadedVm.SelectedTextFontType, ((ComboBox)reloadedPanel.FindName("TextLayerFontTypePicker")!).SelectedItem); Assert.Equal(reloaded.TextFontFamily, ((ComboBox)reloadedPanel.FindName("TextLayerFontPicker")!).SelectedItem); Assert.Equal(reloaded.TextFontFamily, ((ComboBox)reloadedPanel.FindName("TextLayerFontPicker")!).Text); Assert.Equal(reloaded.TextFontSize, ((ComboBox)reloadedPanel.FindName("TextLayerSizePicker")!).SelectedItem); Assert.Equal(reloaded.TextFontSize.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerSizePicker")!).Text); Assert.Equal(reloaded.TextColor, ((TextBox)reloadedPanel.FindName("TextLayerColorEditor")!).Text); Assert.Equal(reloaded.TextColorEntry, ((ComboBox)reloadedPanel.FindName("TextLayerColorPicker")!).SelectedItem); Assert.Equal(reloaded.TextAlignment, ((ComboBox)reloadedPanel.FindName("TextLayerHorizontalAlignmentPicker")!).SelectedItem); Assert.Equal(reloaded.TextAlignment.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerHorizontalAlignmentPicker")!).Text); Assert.Equal(reloaded.TextVerticalAlignment, ((ComboBox)reloadedPanel.FindName("TextLayerVerticalAlignmentPicker")!).SelectedItem); Assert.Equal(reloaded.TextVerticalAlignment.ToString(), ((ComboBox)reloadedPanel.FindName("TextLayerVerticalAlignmentPicker")!).Text); } finally { window?.Close(); MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { File.Delete(dbPath); } catch { /* best-effort cleanup */ } } } private static int FirstInkRow(ytLive.Services.VideoFrame frame) { for (var y = 0; y < frame.Height; y++) for (var x = 0; x < frame.Width; x++) if (frame.BgraPixels[(y * frame.Width + x) * 4 + 3] > 0) return y; return frame.Height; } }