using Bunit;
using Microsoft.AspNetCore.Components;
using ScadaLink.CentralUI.Components.Shared;
namespace ScadaLink.CentralUI.Tests.Shared;
///
/// Regression tests for CentralUI-018. TreeView's storage-restore path
/// called JsonSerializer.Deserialize on the raw treeviewStorage
/// payload outside any try block — a corrupt payload threw an uncaught
/// JsonException during OnAfterRenderAsync, breaking the
/// component. The fix guards the deserialize and ignores a corrupt payload.
///
public class TreeViewStorageResilienceTests : BunitContext
{
private record TestNode(string Key, string Label, List Children);
private static List Roots() => new()
{
new("a", "Alpha", new() { new("a1", "Alpha-1", new()) }),
new("b", "Beta", new()),
};
private IRenderedComponent> BuildTree()
=> Render>(parameters => parameters
.Add(p => p.Items, Roots())
.Add(p => p.ChildrenSelector, n => n.Children)
.Add(p => p.HasChildrenSelector, n => n.Children.Count > 0)
.Add(p => p.KeySelector, n => n.Key)
.Add(p => p.NodeContent, (RenderFragment)(node => b =>
b.AddMarkupContent(0, $"{node.Label}")))
.Add(p => p.StorageKey, "corrupt-tree"));
[Fact]
public void StorageRestore_CorruptJsonPayload_DoesNotThrow_AndStillRenders()
{
// A garbage payload that is not valid JSON for a List.
JSInterop.Setup("treeviewStorage.load", _ => true)
.SetResult("{not json at all]");
JSInterop.SetupVoid("treeviewStorage.save", _ => true);
// Pre-fix: OnAfterRenderAsync threw JsonException out of the unguarded
// Deserialize call. Post-fix: the corrupt payload is ignored.
var cut = BuildTree();
Assert.Contains("Alpha", cut.Markup);
Assert.Contains("Beta", cut.Markup);
}
[Fact]
public void StorageRestore_WrongShapeJson_DoesNotThrow()
{
// Valid JSON, but not a List — an object, not an array.
JSInterop.Setup("treeviewStorage.load", _ => true)
.SetResult("{\"unexpected\": true}");
JSInterop.SetupVoid("treeviewStorage.save", _ => true);
var cut = BuildTree();
Assert.Contains("Alpha", cut.Markup);
}
}