App Settings can now restore only the staged canonical scene. The VM saves pending edits first, resets that scene, reloads immediately, and keeps the same scene staged. Other scene edits survive; the action is disabled while live or recording. 615 tests green, clean build with 0 warnings. Reference: OBS Scene Collections keep scene/source sets distinct: https://obsproject.com/kb/scene-collections
93 lines
3.8 KiB
C#
93 lines
3.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.Data.Sqlite;
|
|
using Xunit;
|
|
using ytLive.Models;
|
|
using ytLive.ViewModels;
|
|
|
|
namespace ytLive.Tests;
|
|
|
|
[Collection("RealApp")]
|
|
public sealed class LayoutResetIntegrationTests
|
|
{
|
|
private readonly RealAppHost _app;
|
|
|
|
public LayoutResetIntegrationTests(RealAppHost app) => _app = app;
|
|
|
|
[Fact]
|
|
public void SettingsRestoreAll_ReplacesEditedScenesWithFactoryLayout() => _app.Run(() =>
|
|
{
|
|
var tempDb = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-reset-{Guid.NewGuid():N}.db");
|
|
MainViewModel.LayoutPathOverride = tempDb;
|
|
MainViewModel? vm = null;
|
|
try
|
|
{
|
|
vm = new MainViewModel();
|
|
var starting = vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Starting));
|
|
starting.Elements.Add(new Source
|
|
{
|
|
Name = "Creator-only layer",
|
|
Type = SourceType.TextOverlay,
|
|
TextContent = "Not in factory layout",
|
|
});
|
|
vm.SaveLayoutNow();
|
|
|
|
Assert.True(vm.RestoreAllLayoutDefaultsCommand.CanExecute(null));
|
|
vm.RestoreAllLayoutDefaultsCommand.Execute(null);
|
|
|
|
Assert.DoesNotContain(vm.Scenes.SelectMany(scene => scene.Elements).OfType<Source>(),
|
|
source => source.Name == "Creator-only layer");
|
|
|
|
var settingsXaml = SourceAssert.Text("Controls", "SettingsDrawer.xaml");
|
|
Assert.Contains("Content=\"Restore all scenes\"", settingsXaml);
|
|
Assert.Contains("Command=\"{Binding RestoreAllLayoutDefaultsCommand}\"", settingsXaml);
|
|
}
|
|
finally
|
|
{
|
|
vm?.Shutdown();
|
|
MainViewModel.LayoutPathOverride = null;
|
|
SqliteConnection.ClearAllPools();
|
|
try { File.Delete(tempDb); } catch { /* best-effort cleanup */ }
|
|
}
|
|
});
|
|
|
|
[Fact]
|
|
public void SettingsRestoreStagedScene_LeavesOtherSceneEditsAndSelectionIntact() => _app.Run(() =>
|
|
{
|
|
var tempDb = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-reset-{Guid.NewGuid():N}.db");
|
|
MainViewModel.LayoutPathOverride = tempDb;
|
|
MainViewModel? vm = null;
|
|
try
|
|
{
|
|
vm = new MainViewModel();
|
|
var starting = vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Starting));
|
|
var brb = vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Brb));
|
|
starting.Elements.Add(new Source { Name = "Keep this edit", Type = SourceType.TextOverlay });
|
|
brb.Elements.Add(new Source { Name = "Reset this edit", Type = SourceType.TextOverlay });
|
|
vm.SaveLayoutNow();
|
|
vm.StagedScene = brb;
|
|
|
|
Assert.True(vm.RestoreStagedSceneDefaultsCommand.CanExecute(null));
|
|
vm.RestoreStagedSceneDefaultsCommand.Execute(null);
|
|
|
|
Assert.Contains(vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Starting))
|
|
.Elements.OfType<Source>(), source => source.Name == "Keep this edit");
|
|
Assert.DoesNotContain(vm.Scenes.Single(scene => SceneCatalog.Is(scene.Name, SceneCatalog.Brb))
|
|
.Elements.OfType<Source>(), source => source.Name == "Reset this edit");
|
|
Assert.True(SceneCatalog.Is(vm.StagedScene?.Name, SceneCatalog.Brb));
|
|
|
|
var settingsXaml = SourceAssert.Text("Controls", "SettingsDrawer.xaml");
|
|
Assert.Contains("Content=\"Restore staged scene\"", settingsXaml);
|
|
Assert.Contains("Command=\"{Binding RestoreStagedSceneDefaultsCommand}\"", settingsXaml);
|
|
}
|
|
finally
|
|
{
|
|
vm?.Shutdown();
|
|
MainViewModel.LayoutPathOverride = null;
|
|
SqliteConnection.ClearAllPools();
|
|
try { File.Delete(tempDb); } catch { /* best-effort cleanup */ }
|
|
}
|
|
});
|
|
}
|