feat(37): keep a default layout snapshot beside the current layout
The matching-build persistence slice is in place: existing layouts are captured once as defaults, first-run factory scenes are saved and captured before the creator can edit, and same-build startup continues to load current rows. Default asset references survive current-layout saves. One integration test covers the current-layout roundtrip and immutable default. 609 tests green, clean build with 0 warnings. Reference scan: OBS stores scene collections separately from output profiles; this split keeps layout state independent in the same SQLite store: https://obsproject.com/kb/scene-collections
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
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 */ }
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user