using System.Security.Claims; using Bunit; using Bunit.TestDoubles; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using NSubstitute; using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Templates; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Transport; using ZB.MOM.WW.ScadaBridge.Commons.Types; using ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening; using ZB.MOM.WW.ScadaBridge.Communication; using ZB.MOM.WW.ScadaBridge.DeploymentManager; using ZB.MOM.WW.ScadaBridge.Security; using ZB.MOM.WW.ScadaBridge.TemplateEngine.Services; using InstanceCreatePage = ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Deployment.InstanceCreate; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Deployment; /// /// bUnit tests for the Create Instance template field: a read-only path box plus a /// Choose… button that opens TemplatePickerDialog, and the ?templateId= /// query preselect (including the dangling-id hint and the no-templates empty state). /// public class InstanceCreateTemplateFieldTests : BunitContext { private readonly ITemplateEngineRepository _repo = Substitute.For(); private readonly ISiteRepository _siteRepo = Substitute.For(); private readonly IDeploymentManagerRepository _deployRepo = Substitute.For(); private readonly IFlatteningPipeline _pipeline = Substitute.For(); private readonly IAuditService _audit = Substitute.For(); private readonly DialogService _dialog = new(); public InstanceCreateTemplateFieldTests() { Services.AddSingleton(_repo); Services.AddSingleton(_siteRepo); Services.AddSingleton(_deployRepo); Services.AddSingleton(_pipeline); Services.AddSingleton(_audit); // The Connection Bindings card renders NodeBrowserDialog once a site is chosen. Services.AddSingleton(Substitute.For()); // DeploymentService / InstanceService have non-mockable concrete deps; // instantiate them directly (same block TopologyPageTests uses). Services.AddSingleton(new CommunicationService( Options.Create(new CommunicationOptions()), NullLogger.Instance)); Services.AddSingleton(new OperationLockManager()); Services.AddSingleton(Options.Create(new DeploymentManagerOptions { OperationLockTimeout = TimeSpan.FromSeconds(5) })); Services.AddSingleton(Options.Create(new CommunicationOptions())); Services.AddSingleton>(NullLogger.Instance); Services.AddScoped(); Services.AddScoped(); Services.AddSingleton( new DeploymentStatusNotifier(NullLogger.Instance)); Services.AddSingleton(Substitute.For()); Services.AddScoped(); Services.AddScoped(); Services.AddScoped(); Services.AddScoped(); // A real DialogService behind a real DialogHost so Choose… actually opens. Services.AddSingleton(_dialog); var claims = new[] { new Claim(JwtTokenService.UsernameClaimType, "tester"), new Claim(JwtTokenService.RoleClaimType, "Deployer") }; Services.AddSingleton( new TestAuthStateProvider(new ClaimsPrincipal(new ClaimsIdentity(claims, "TestAuth")))); Services.AddAuthorizationCore(); JSInterop.Mode = JSRuntimeMode.Loose; } /// Folders A → B with template 7 "Deep"; folder Other with template 8 "Elsewhere". private void SeedCatalogue(bool empty = false, bool withSite = false) { var folders = empty ? new List() : new List { new("A") { Id = 1 }, new("B") { Id = 2, ParentFolderId = 1 }, new("Other") { Id = 3 }, }; var templates = empty ? new List