using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; /// /// Verifies the zoom box created by a right-click in the live preview: each /// ZoomView Shape procures the right bounding box (circle is square and /// centered on the click, phone is a tall 9:16 rect, tablet a wide 16:9 rect /// both anchored top-left at the click), the box stays fully inside the /// 1920x1080 preview, and the UI renders the matching outline with the zoomed /// region clipped to the shape. /// [Collection("RealApp")] public sealed class ZoomBoxInteractionTests { private readonly RealAppHost _app; public ZoomBoxInteractionTests(RealAppHost app) { _app = app; } [Fact] public void Zoom_Shape_Controls_Box_Aspect_Anchor_And_Render() { _app.Run(Run); } private void Run() { var tempDb = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"ytLlive-test-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; var window = new MainWindow(); var vm = (MainViewModel)window.DataContext; try { window.Show(); window.UpdateLayout(); // Same internal test seam as IsRecording allows ActivateZoom (IsEditMode goes false). vm.IsRecording = true; var pane = (UserControl)window.FindName("PreviewPane")!; var zoomBox = (Grid)pane.FindName("ZoomBox")!; var rectOutline = (Rectangle)pane.FindName("ZoomRectOutline")!; var circleOutline = (Ellipse)pane.FindName("ZoomCircleOutline")!; // Circle: square box, click point is the CENTER. vm.ZoomShape = ZoomShape.Circle; vm.ActivateZoom(1000, 500); Assert.True(vm.IsZoomActive); Assert.Equal(vm.ZoomState.Width, vm.ZoomState.Height, 3); Assert.Equal(1000 - vm.ZoomState.Width / 2, vm.ZoomState.X, 3); Assert.Equal(500 - vm.ZoomState.Height / 2, vm.ZoomState.Y, 3); window.UpdateLayout(); Assert.Equal(Visibility.Visible, zoomBox.Visibility); Assert.IsType(zoomBox.Clip); Assert.Equal(Visibility.Visible, circleOutline.Visibility); Assert.Equal(Visibility.Collapsed, rectOutline.Visibility); // Phone (vertical rectangle): tall 9:16 box, click point is the TOP-LEFT corner. vm.ZoomShape = ZoomShape.VerticalRectangle; vm.ActivateZoom(200, 100); Assert.True(vm.ZoomState.Height > vm.ZoomState.Width); Assert.Equal(9.0 / 16.0, vm.ZoomState.Width / vm.ZoomState.Height, 3); Assert.Equal(200, vm.ZoomState.X, 3); Assert.Equal(100, vm.ZoomState.Y, 3); window.UpdateLayout(); Assert.Null(zoomBox.Clip); Assert.Equal(Visibility.Collapsed, circleOutline.Visibility); Assert.Equal(Visibility.Visible, rectOutline.Visibility); // Tablet (horizontal rectangle): wide 16:9 box, anchored top-left. vm.ZoomShape = ZoomShape.HorizontalRectangle; vm.ActivateZoom(200, 100); Assert.True(vm.ZoomState.Width > vm.ZoomState.Height); Assert.Equal(16.0 / 9.0, vm.ZoomState.Width / vm.ZoomState.Height, 3); Assert.Equal(200, vm.ZoomState.X, 3); Assert.Equal(100, vm.ZoomState.Y, 3); // Clamp keeps the box fully inside the 1920x1080 preview even for a // corner click that would otherwise overhang it. vm.ActivateZoom(2000, 2000); const double frameW = 1920, frameH = 1080; Assert.True(vm.ZoomState.X >= 0 && vm.ZoomState.Y >= 0); Assert.True(vm.ZoomState.X + vm.ZoomState.Width <= frameW); Assert.True(vm.ZoomState.Y + vm.ZoomState.Height <= frameH); } finally { window.Close(); MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { System.IO.File.Delete(tempDb); } catch { } } } }