Webcam menu gates on the app-wide identity (TASK 26)
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Xunit;
|
||||
using ytLive.Models;
|
||||
using ytLive.ViewModels;
|
||||
|
||||
namespace ytLive.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// TASK 26 integration: the (+) menu's Webcam row gates on the app-wide webcam
|
||||
/// identity — one camera per app, so the row must stay disabled while ANY scene
|
||||
/// shows the webcam (not just the staged one), and re-enable only after the
|
||||
/// last config anywhere is removed (which also drops the identity).
|
||||
/// Real-App + temp-DB pattern (see BackgroundHealIntegrationTests).
|
||||
/// </summary>
|
||||
[Collection("RealApp")]
|
||||
public sealed class WebcamMenuGateTests
|
||||
{
|
||||
[Fact]
|
||||
public void CanAddWebcam_Gates_On_The_AppWide_Webcam_Identity()
|
||||
{
|
||||
_app.Run(Run);
|
||||
}
|
||||
|
||||
private readonly RealAppHost _app;
|
||||
|
||||
public WebcamMenuGateTests(RealAppHost app) => _app = app;
|
||||
|
||||
private void Run()
|
||||
{
|
||||
var tempDb = Path.Combine(Path.GetTempPath(), $"ytLlive-wcgate-{Guid.NewGuid():N}.db");
|
||||
MainViewModel.LayoutPathOverride = tempDb;
|
||||
var window = default(MainWindow);
|
||||
try
|
||||
{
|
||||
using (var schema = new ytLive.Services.LayoutStore(tempDb)) { }
|
||||
SqliteConnection.ClearAllPools();
|
||||
SeedDatabaseWithWebcam(tempDb);
|
||||
|
||||
window = new MainWindow();
|
||||
var vm = (MainViewModel)window.DataContext;
|
||||
|
||||
var starting = vm.Scenes.Single(s => SceneCatalog.Is(s.Name, SceneCatalog.Starting));
|
||||
var live = vm.Scenes.Single(s => SceneCatalog.Is(s.Name, SceneCatalog.Live));
|
||||
|
||||
vm.StagedScene = live;
|
||||
Assert.True(live.WebcamConfig == null, "Live must not carry the webcam config");
|
||||
Assert.False(vm.CanAddWebcam,
|
||||
"webcam exists in another scene — Add Webcam must be greyed out app-wide");
|
||||
|
||||
vm.StagedScene = starting;
|
||||
Assert.False(vm.CanAddWebcam, "staged scene itself has the webcam");
|
||||
|
||||
var config = starting.WebcamConfig!;
|
||||
vm.RemoveSourceCommand.Execute(config);
|
||||
|
||||
Assert.True(vm.CanAddWebcam,
|
||||
"last webcam config anywhere was removed — identity cleared, picker may run again");
|
||||
|
||||
vm.SaveLayoutNow();
|
||||
using (var connection = new SqliteConnection($"Data Source={tempDb}"))
|
||||
{
|
||||
connection.Open();
|
||||
using var webcams = connection.CreateCommand();
|
||||
webcams.CommandText = "SELECT COUNT(*) FROM Webcam;";
|
||||
Assert.Equal(0L, (long)webcams.ExecuteScalar()!);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
window?.Close();
|
||||
MainViewModel.LayoutPathOverride = null;
|
||||
SqliteConnection.ClearAllPools();
|
||||
try { File.Delete(tempDb); } catch { /* best-effort cleanup */ }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Five canonical scenes + a webcam identity used by exactly one
|
||||
/// non-staged-by-default scene (Starting), so staging any other screen
|
||||
/// reproduces the old per-scene gate's false "available".</summary>
|
||||
private static void SeedDatabaseWithWebcam(string path)
|
||||
{
|
||||
using var connection = new SqliteConnection($"Data Source={path}");
|
||||
connection.Open();
|
||||
|
||||
var scenes = new (string Id, string Name)[]
|
||||
{
|
||||
("scene-starting", "Starting"),
|
||||
("scene-live", "Live"),
|
||||
("scene-brb", "BRB"),
|
||||
("scene-chat", "Chat"),
|
||||
("scene-ending", "Ending"),
|
||||
};
|
||||
foreach (var (id, name) in scenes)
|
||||
{
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText =
|
||||
"INSERT INTO Scene (Id, Name, HasBackground, SortOrder) VALUES ($id, $name, 1, $order);";
|
||||
cmd.Parameters.AddWithValue("$id", id);
|
||||
cmd.Parameters.AddWithValue("$name", name);
|
||||
cmd.Parameters.AddWithValue("$order", Array.IndexOf(scenes, (id, name)));
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (var webcam = connection.CreateCommand())
|
||||
{
|
||||
webcam.CommandText =
|
||||
"INSERT INTO Webcam (Id, DeviceId, Name) VALUES ('wc-1', 'test-camera', 'Test Cam');";
|
||||
webcam.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
using (var config = connection.CreateCommand())
|
||||
{
|
||||
config.CommandText =
|
||||
@"INSERT INTO WebcamSceneConfig
|
||||
(SceneId, WebcamId, IsVisible, X, Y, Width, Height, Opacity, SortOrder)
|
||||
VALUES ('scene-starting', 'wc-1', 1, 100, 100, 480, 270, 1, 0);";
|
||||
config.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user