Files
LlamaCasty/ytLive.Tests/LayoutStoreSnapshotTests.cs
T
gramps 1c6fc3223d feat(37): restore the default layout when the build ID changes
A mismatched or missing current-build stamp restores the immutable default
snapshot atomically before the VM loads scenes. The new integration case edits
current on build A, opens on build B, and verifies the factory layout returns.
610 tests green, clean build with 0 warnings.

Reference: OBS scene collections keep scenes/sources as a separate saved set:
https://obsproject.com/kb/scene-collections
2026-11-10 17:48:43 -08:00

97 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Linq;
using Microsoft.Data.Sqlite;
using Xunit;
using ytLive.Models;
using ytLive.Services;
namespace ytLive.Tests;
public sealed class LayoutStoreSnapshotTests
{
[Fact]
public void SameBuild_OpensCurrentLayout_WithoutChangingDefaultSnapshot()
{
var path = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-snapshot-{Guid.NewGuid():N}.db");
const string buildId = "build-a";
try
{
using (var store = new LayoutStore(path))
{
var factory = MakeScene("Factory title");
store.Save(new[] { factory }, null, null);
store.PrepareLayoutSnapshots(buildId);
store.Save(new[] { MakeScene("Creator edit") }, null, null);
}
using (var reopened = new LayoutStore(path))
{
reopened.PrepareLayoutSnapshots(buildId);
var current = Assert.Single(reopened.Load());
Assert.Equal("Creator edit", Assert.Single(current.Elements.OfType<Source>()).Name);
using var connection = GetConnection(path);
using var command = connection.CreateCommand();
command.CommandText = "SELECT Value FROM LayoutSnapshotState WHERE Key = 'CurrentBuildId';";
Assert.Equal(buildId, command.ExecuteScalar());
command.CommandText = "SELECT Name FROM DefaultSource;";
Assert.Equal("Factory title", command.ExecuteScalar());
}
}
finally
{
SqliteConnection.ClearAllPools();
try { File.Delete(path); } catch { /* best-effort cleanup */ }
}
}
[Fact]
public void DifferentBuild_RestoresTheDefaultSnapshotBeforeLoading()
{
var path = Path.Combine(Path.GetTempPath(), $"ytLlive-layout-snapshot-{Guid.NewGuid():N}.db");
try
{
using (var store = new LayoutStore(path))
{
store.Save(new[] { MakeScene("Factory title") }, null, null);
store.PrepareLayoutSnapshots("build-a");
store.Save(new[] { MakeScene("Creator edit") }, null, null);
}
using (var reopened = new LayoutStore(path))
{
reopened.PrepareLayoutSnapshots("build-b");
var restored = Assert.Single(reopened.Load());
Assert.Equal("Factory title", Assert.Single(restored.Elements.OfType<Source>()).Name);
using var connection = GetConnection(path);
using var command = connection.CreateCommand();
command.CommandText = "SELECT Value FROM LayoutSnapshotState WHERE Key = 'CurrentBuildId';";
Assert.Equal("build-b", command.ExecuteScalar());
}
}
finally
{
SqliteConnection.ClearAllPools();
try { File.Delete(path); } catch { /* best-effort cleanup */ }
}
}
private static Scene MakeScene(string sourceName)
=> new()
{
Name = SceneCatalog.Starting,
Elements = { new Source { Name = sourceName, Type = SourceType.TextOverlay } },
};
private static SqliteConnection GetConnection(string path)
{
var connection = new SqliteConnection($"Data Source={path}");
connection.Open();
return connection;
}
}