Files
LlamaCasty/ytLive.Tests/TextLayerDropdownTests.cs
T
gramps 5f7bcc2425 fix(text): show selected formatting and style controls
Use category-filtered font and selected-item dropdowns, separate horizontal and vertical alignment, and reuse the border-color palette templates for text color. Persist vertical alignment additively. Follow the established static text-source pattern: https://obsproject.com/kb/text-sources
2026-11-04 17:05:06 -08:00

154 lines
7.6 KiB
C#

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<Source>()
.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<string>().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<ytLive.Services.VideoFrame>(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<Source>()
.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;
}
}