using Xunit; namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.Cluster; /// /// TDD coverage for the typed fixture helpers used by /// state-changing Central UI Playwright E2E tests to provision and tear down /// templates, attributes, areas, and instances against the running dev cluster. /// When the cluster / MSSQL is unreachable the facts report as Skipped (not /// Failed), matching the established suite idiom. /// [Collection("Playwright")] public class CliRunnerHelpersTests { /// /// A freshly created template is discoverable by name prefix and can be /// deleted, exercising , /// , and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteTemplate_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var name = CliRunner.UniqueName("tmpl"); int id = await CliRunner.CreateTemplateAsync(name); try { var ids = await CliRunner.ListTemplateIdsByNamePrefixAsync(name); Assert.Contains(id, ids); } finally { await CliRunner.DeleteTemplateAsync(id); } } /// /// finds the well-known /// site-a seed site by its siteIdentifier and returns a /// positive id. /// [SkippableFact] public async Task ResolveSiteA_ReturnsId() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); Assert.True(await CliRunner.ResolveSiteIdAsync("site-a") > 0); } /// /// A freshly created data connection returns a positive id and is cleanly /// deleted in teardown, exercising /// and as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteDataConnection_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var siteId = await CliRunner.ResolveSiteIdAsync("site-a"); var id = await CliRunner.CreateDataConnectionAsync(siteId, CliRunner.UniqueName("conn")); try { Assert.True(id > 0); } finally { await CliRunner.DeleteDataConnectionAsync(id); } } /// /// A freshly created API method returns a positive id and is cleanly deleted in /// teardown, exercising and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteApiMethod_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var id = await CliRunner.CreateApiMethodAsync(CliRunner.UniqueName("method")); try { Assert.True(id > 0); } finally { await CliRunner.DeleteApiMethodAsync(id); } } /// /// A freshly created area is discoverable by name prefix via /// , confirming the round-trip /// used by UI tests that need to tear down areas whose ids are never surfaced. /// Exercises , /// , and /// . /// [SkippableFact] public async Task ListAreaIdsByNamePrefix_FindsCreatedArea() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var siteId = await CliRunner.ResolveSiteIdAsync("site-a"); var name = CliRunner.UniqueName("listarea"); var areaId = await CliRunner.CreateAreaAsync(siteId, name); try { var ids = await CliRunner.ListAreaIdsByNamePrefixAsync(siteId, name); Assert.Contains(areaId, ids); } finally { await CliRunner.DeleteAreaAsync(areaId); } } /// /// A freshly created external system is discoverable by name prefix and is cleanly /// deleted in teardown, exercising , /// , and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteExternalSystem_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var name = CliRunner.UniqueName("extsys"); var id = await CliRunner.CreateExternalSystemAsync(name); try { Assert.True(id > 0); Assert.Contains(id, await CliRunner.ListExternalSystemIdsByNamePrefixAsync(name)); } finally { await CliRunner.DeleteExternalSystemAsync(id); } } /// /// A freshly created notification list is discoverable by name prefix and is cleanly /// deleted in teardown, exercising , /// , and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteNotificationList_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var name = CliRunner.UniqueName("notiflist"); var id = await CliRunner.CreateNotificationListAsync(name); try { Assert.True(id > 0); Assert.Contains(id, await CliRunner.ListNotificationListIdsByNamePrefixAsync(name)); } finally { await CliRunner.DeleteNotificationListAsync(id); } } /// /// A freshly created shared script returns a positive id and is cleanly deleted in /// teardown, exercising and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteSharedScript_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var id = await CliRunner.CreateSharedScriptAsync(CliRunner.UniqueName("script")); try { Assert.True(id > 0); } finally { await CliRunner.DeleteSharedScriptAsync(id); } } /// /// A freshly created LDAP→role mapping returns a positive id, is discoverable by its /// ldapGroupName in security role-mapping list, and is cleanly deleted in /// teardown, exercising and /// as a round-trip. /// [SkippableFact] public async Task CreateThenDeleteRoleMapping_RoundTrips() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var group = CliRunner.UniqueName("grp"); var id = await CliRunner.CreateRoleMappingAsync(group, "Designer"); try { Assert.True(id > 0); using var list = await CliRunner.RunJsonAsync("security", "role-mapping", "list"); Assert.Contains( list.RootElement.EnumerateArray(), e => e.TryGetProperty("ldapGroupName", out var n) && n.GetString() == group); } finally { await CliRunner.DeleteRoleMappingAsync(id); } } }