From d54013cb88f03b624bd98899afc01479f4159971 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 11 May 2026 11:25:15 -0400 Subject: [PATCH] test(ui/templates): bUnit rendering tests for folder tree --- .../TemplatesPageTests.cs | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 tests/ScadaLink.CentralUI.Tests/TemplatesPageTests.cs diff --git a/tests/ScadaLink.CentralUI.Tests/TemplatesPageTests.cs b/tests/ScadaLink.CentralUI.Tests/TemplatesPageTests.cs new file mode 100644 index 0000000..736a0bc --- /dev/null +++ b/tests/ScadaLink.CentralUI.Tests/TemplatesPageTests.cs @@ -0,0 +1,129 @@ +using System.Security.Claims; +using Bunit; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using ScadaLink.Commons.Entities.Templates; +using ScadaLink.Commons.Interfaces.Repositories; +using ScadaLink.Commons.Interfaces.Services; +using ScadaLink.TemplateEngine; +using ScadaLink.TemplateEngine.Services; +using TemplatesPage = ScadaLink.CentralUI.Components.Pages.Design.Templates; + +namespace ScadaLink.CentralUI.Tests; + +/// +/// bUnit rendering tests for the Templates page that verify the folder/template +/// tree builds the expected DOM for the main shape categories: empty state, +/// folder-containing-template nesting, and composition leaves under their owner. +/// +public class TemplatesPageTests : BunitContext +{ + private readonly ITemplateEngineRepository _repo = Substitute.For(); + private readonly IAuditService _audit = Substitute.For(); + + public TemplatesPageTests() + { + // The page's TemplateService / TemplateFolderService are constructed via DI + // from the repository and audit service, mirroring real Host wiring. + Services.AddSingleton(_repo); + Services.AddSingleton(_audit); + Services.AddScoped(); + Services.AddScoped(); + AddTestAuth(); + + // The TreeView inside the page persists expansion state via JS interop + // against sessionStorage (`templates-tree` key). bUnit requires explicit + // stubs for all JS interop calls, otherwise rendering throws. + JSInterop.Setup("treeviewStorage.load", _ => true).SetResult(null); + JSInterop.SetupVoid("treeviewStorage.save", _ => true); + } + + private void AddTestAuth() + { + // The page resolves the current user via the "Username" claim in + // GetCurrentUserAsync(); supply a stub so OnInitializedAsync doesn't crash. + var claims = new[] + { + new Claim("Username", "tester"), + new Claim(ClaimTypes.Role, "Design") + }; + var identity = new ClaimsIdentity(claims, "TestAuth"); + var user = new ClaimsPrincipal(identity); + Services.AddSingleton(new TestAuthStateProvider(user)); + Services.AddAuthorizationCore(); + } + + [Fact] + public void Renders_EmptyState_WhenNoTemplatesOrFolders() + { + _repo.GetAllTemplatesAsync(Arg.Any()) + .Returns(Task.FromResult>(new List