using System; using System.IO; using System.Linq; using Microsoft.Data.Sqlite; using Xunit; using ytLive.Models; using ytLive.ViewModels; namespace ytLive.Tests; /// /// TASK 57, the "vv" feature, Unit 2 — the vertical (9:16) tier's CHAT scene /// camera. /// /// Unit 1 gave every scene its own vertical placement. Unit 2 is the Chat /// scene's own rules (the creator's table, 2026-10-17): in the vertical tier /// the Chat camera is **rect only — the circle option is not offered** — and /// its size is either the normal small tile or **enlarged to fill one whole /// 607×540 area** (the top one or the bottom one, by where the camera is). /// /// One test, the whole story (the Good Dog rule): the vertical tier is picked → /// the Chat camera comes into the band as a small RECT tile → the circle option /// is not offered and cannot be set even by the model → the camera is dragged up /// and enlarged, and it fills the TOP area exactly → switching back to 16:9 /// restores the desktop layout exactly (and the circle option is offered again). /// [Collection("RealApp")] public sealed class VerticalChatCameraLayoutTests { private readonly RealAppHost _app; public VerticalChatCameraLayoutTests(RealAppHost app) => _app = app; [Fact] public void Vertical_Tier_Chat_Camera_Is_Rect_Only_And_Enlarges_To_One_Area() { _app.Run(Run); } private void Run() { var tempDb = Path.Combine(Path.GetTempPath(), $"ytLlive-vv-chat-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; try { var vm = new MainViewModel(); var chat = vm.Scenes.First(s => s.Name == "Chat"); var camera = new WebcamSceneConfig { WebcamId = "webcam-1", Name = "Webcam", X = 120, Y = 120, Width = 640, Height = 360, }; chat.Elements.Add(camera); // The 16:9 placement: the camera sits where the desktop layout put it. Assert.Equal(120, camera.X); Assert.Equal(120, camera.Y); Assert.Equal(640, camera.Width); // ── The vertical tier is picked ─────────────────────────────────── vm.SelectedQuality = vm.QualityOptions[^1]; Assert.True(vm.IsVerticalTier); var band = vm.VerticalBand; // The Chat camera came INTO the band as a small tile... Assert.Equal(VerticalCameraLayout.TileWidth, camera.Width); Assert.Equal(VerticalCameraLayout.TileHeight, camera.Height); Assert.True(camera.X >= band.Left, $"camera X {camera.X} is left of the band {band.Left}"); Assert.True(camera.X + camera.Width <= band.Right, "the camera hangs over the band's right edge"); Assert.True(camera.Y >= band.Top, "the camera hangs over the band's top edge"); Assert.True(camera.Y + camera.Height <= band.Bottom, "the camera hangs over the band's bottom edge"); // ── The circle option is not offered ───────────────────────────── vm.SelectedElement = camera; Assert.False(vm.CanToggleClipShape); Assert.Equal(ClipShape.Traditional, camera.ClipShape); // ...and it cannot be slipped in behind the UI's back either. camera.ToggleClipShape(); Assert.Equal(ClipShape.Traditional, camera.ClipShape); // ── Drag it up, then enlarge it: it fills the TOP area ────────── vm.MoveWebcamInVerticalTier(camera, band.Left + 40, band.Top + 40); vm.ResizeWebcamInVerticalTier(camera, band.Width, band.Height); Assert.Equal(band.Left, camera.X, 3); Assert.Equal(band.Top, camera.Y, 3); Assert.Equal(band.Width, camera.Width, 3); Assert.Equal(band.Height / 2, camera.Height, 3); // ── Back to 16:9: the desktop layout is restored exactly ───────── vm.SelectedQuality = vm.QualityOptions[0]; Assert.False(vm.IsVerticalTier); Assert.Equal(120, camera.X); Assert.Equal(120, camera.Y); Assert.Equal(640, camera.Width); Assert.Equal(360, camera.Height); // The circle option is offered again outside the vertical tier. Assert.True(vm.CanToggleClipShape); } finally { MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { File.Delete(tempDb); } catch { /* best-effort cleanup */ } } } }