docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)

Comment/XML-doc changes only:
- add summaries to ~10k test methods, fixtures, fakes and helpers
  (+ <param> on theories, <returns> on async Task methods,
  <inheritdoc/> on interface implementations the checker can resolve)
- strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N,
  #NN, Component-0NN) from comments, keeping the explanatory text;
  reword false positives in comments only
- real docs on fakes implementing BCL/library interfaces
  (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime)
- reword the last 5 src/ false positives (CWE-1236, failures-1,
  year-0001, M365)

Only non-comment edits: four one-line nested classes split across lines
so members can carry docs. Build 0 errors / 0 warnings.
This commit is contained in:
Joseph Doherty
2026-10-07 15:05:49 -04:00
parent 0ffd4bdbea
commit 513fa1aa16
998 changed files with 17896 additions and 2395 deletions
@@ -29,6 +29,7 @@ public class AlarmSummaryRenderTests : BunitContext
private readonly ISiteRepository _siteRepo = Substitute.For<ISiteRepository>();
private readonly FakeSiteAlarmLiveCache _liveCache = new();
/// <summary>Initializes the test class and configures the faked services and the bUnit context.</summary>
public AlarmSummaryRenderTests()
{
// Two rows whose default sort (severity DESC) orders Zeta (900) before
@@ -41,7 +42,7 @@ public class AlarmSummaryRenderTests : BunitContext
_summary.GetSiteAlarmsAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
.Returns(Task.FromResult(new AlarmSummaryResult(rows, Array.Empty<string>())));
// BuildFromLiveAlarms (Task 5): flatten the pushed live snapshot the same way
// BuildFromLiveAlarms: flatten the pushed live snapshot the same way
// the real service does, so the live-path render tests exercise real behavior.
_summary.BuildFromLiveAlarms(Arg.Any<IReadOnlyList<AlarmStateChanged>>())
.Returns(ci =>
@@ -90,6 +91,7 @@ public class AlarmSummaryRenderTests : BunitContext
return cut;
}
/// <summary>Verifies that sortable headers carry a tabindex and an aria-sort attribute.</summary>
[Fact]
public void SortableHeaders_CarryTabindexAndAriaSort()
{
@@ -113,6 +115,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.Null(stateKind.GetAttribute("aria-sort"));
}
/// <summary>Verifies that pressing Enter on the instance header flips the row order.</summary>
[Fact]
public void EnterOnInstanceHeader_FlipsRowOrder()
{
@@ -133,8 +136,9 @@ public class AlarmSummaryRenderTests : BunitContext
cut.FindAll("tr[data-test='alarm-summary-row']")[0]
.QuerySelector("td")!.TextContent.Trim();
// ── plan #10 Task 5: live-cache-first with poll fallback ───────────────────
// ── live-cache-first with poll fallback ───────────────────
/// <summary>Verifies that selecting a site subscribes to the live cache.</summary>
[Fact]
public void SelectingSite_SubscribesToTheLiveCache()
{
@@ -144,6 +148,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.Equal(1, _liveCache.LastSubscribedSite);
}
/// <summary>Verifies that the poll fallback renders when the live cache is not live yet.</summary>
[Fact]
public void PollFallbackRenders_WhenCacheNotLiveYet()
{
@@ -157,6 +162,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.Equal("Zeta", FirstRowInstance(cut)); // severity-desc default
}
/// <summary>Verifies that a change notification rebuilds the rendered rows from the live snapshot.</summary>
[Fact]
public void OnChangedDelta_RebuildsRenderedRowsFromLiveSnapshot()
{
@@ -176,6 +182,7 @@ public class AlarmSummaryRenderTests : BunitContext
});
}
/// <summary>Verifies that leaving a site unsubscribes from the live cache.</summary>
[Fact]
public void LeavingSite_UnsubscribesFromTheLiveCache()
{
@@ -188,6 +195,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.Equal(1, _liveCache.DisposeCount);
}
/// <summary>Verifies that changing the site resubscribes to the new site.</summary>
[Fact]
public void ChangingSite_ResubscribesToTheNewSite()
{
@@ -200,6 +208,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.Equal(2, _liveCache.LastSubscribedSite);
}
/// <summary>Verifies that disposing the component unsubscribes from the live cache.</summary>
[Fact]
public void DisposingComponent_UnsubscribesFromTheLiveCache()
{
@@ -212,6 +221,7 @@ public class AlarmSummaryRenderTests : BunitContext
// ── arch-review R2 N4: stale-site poll guard ───────────────────────────────
/// <summary>Verifies that an in-flight poll for the previous site does not overwrite the new site's rows.</summary>
[Fact]
public void InFlightPollForPreviousSite_DoesNotOverwriteNewSitesRows()
{
@@ -231,7 +241,7 @@ public class AlarmSummaryRenderTests : BunitContext
cut.Find("[data-test='alarm-summary-site']").Change("2"); // site 2 renders
cut.WaitForAssertion(() => Assert.Equal("Site2Instance", FirstRowInstance(cut)));
// The stale site-1 fan-out now completes — it must be dropped, not rendered.
// The stale first-site fan-out now completes — it must be dropped, not rendered.
site1Tcs.SetResult(new AlarmSummaryResult(
new List<AlarmSummaryRow>
{
@@ -248,6 +258,7 @@ public class AlarmSummaryRenderTests : BunitContext
// ── arch-review R2 N5: while live, the poll updates only _notReporting ──────
/// <summary>Verifies that a poll while live updates only the not-reporting list and does not regress the live rows.</summary>
[Fact]
public void PollWhileLive_UpdatesNotReportingOnly_DoesNotRegressLiveRows()
{
@@ -280,9 +291,10 @@ public class AlarmSummaryRenderTests : BunitContext
});
}
// ── arch-review P6-2: site scoping (a scoped Deployer must not watch another
// ── site scoping (a scoped Deployer must not watch another
// site's live alarms — the page was missed by the ad0100f2 scoping survey) ──
/// <summary>Verifies that a site-scoped deployment user sees only the permitted site in the picker.</summary>
[Fact]
public void SiteScoping_ScopedDeploymentUser_SeesOnlyPermittedSiteInPicker()
{
@@ -302,6 +314,7 @@ public class AlarmSummaryRenderTests : BunitContext
Assert.DoesNotContain("Site 2", cut.Markup);
}
/// <summary>Verifies that a forged out-of-scope site id is denied and never fetched.</summary>
[Fact]
public void SiteScoping_ForgedOutOfScopeSiteId_IsDeniedNotFetched()
{
@@ -329,6 +342,7 @@ public class AlarmSummaryRenderTests : BunitContext
// ── arch-review R2 N7: disposal guard on the live callback ─────────────────
/// <summary>Verifies that a live callback racing with disposal is dropped without a rebuild or an exception.</summary>
[Fact]
public void LiveCallbackRacingDispose_IsDropped_NoRebuildNoThrow()
{
@@ -363,11 +377,16 @@ public class AlarmSummaryRenderTests : BunitContext
private IReadOnlyList<AlarmStateChanged> _current = Array.Empty<AlarmStateChanged>();
private bool _live;
/// <summary>Gets the number of subscribe calls received.</summary>
public int SubscribeCount { get; private set; }
/// <summary>Gets the number of subscriptions disposed.</summary>
public int DisposeCount { get; private set; }
/// <summary>Gets the site id of the most recent subscribe call.</summary>
public int? LastSubscribedSite { get; private set; }
/// <summary>Gets the change callback captured by the most recent subscribe call.</summary>
public Action? CapturedCallback => _onChanged;
/// <inheritdoc />
public IDisposable Subscribe(int siteId, Action onChanged)
{
SubscribeCount++;
@@ -376,8 +395,10 @@ public class AlarmSummaryRenderTests : BunitContext
return new Subscription(this);
}
/// <inheritdoc />
public IReadOnlyList<AlarmStateChanged> GetCurrentAlarms(int siteId) => _current;
/// <inheritdoc />
public bool IsLive(int siteId) => _live;
/// <summary>
@@ -386,8 +407,11 @@ public class AlarmSummaryRenderTests : BunitContext
/// </summary>
public IReadOnlyList<string> NotReporting { get; set; } = Array.Empty<string>();
/// <inheritdoc />
public IReadOnlyList<string> GetNotReportingInstances(int siteId) => NotReporting;
/// <summary>Replaces the current snapshot, marks the cache live and raises the change callback.</summary>
/// <param name="alarms">The alarm snapshot to publish.</param>
public void PushAlarms(IReadOnlyList<AlarmStateChanged> alarms)
{
_current = alarms;
@@ -400,8 +424,11 @@ public class AlarmSummaryRenderTests : BunitContext
private readonly FakeSiteAlarmLiveCache _owner;
private bool _disposed;
/// <summary>Initializes the subscription for the given fake cache.</summary>
/// <param name="owner">The fake cache that issued the subscription.</param>
public Subscription(FakeSiteAlarmLiveCache owner) => _owner = owner;
/// <summary>Releases the resources held by this instance.</summary>
public void Dispose()
{
if (_disposed) return;
@@ -15,7 +15,7 @@ using AlarmSummaryPage = ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Monito
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Monitoring;
/// <summary>
/// Covers the Alarm Summary flat table's two rendering paths (arch-review WP2.4). A short
/// Covers the Alarm Summary flat table's two rendering paths. A short
/// list renders every row with a plain foreach; past the threshold the same row template is
/// handed to <c>Virtualize</c> so a site with thousands of alarms stops materialising the
/// whole table into the circuit's render tree on every delta. Row markup — including the
@@ -69,6 +69,7 @@ public class AlarmSummaryVirtualizeTests : BunitContext
return cut;
}
/// <summary>Verifies that a short alarm list renders every row inline.</summary>
[Fact]
public void ShortList_RendersEveryRowInline()
{
@@ -82,6 +83,7 @@ public class AlarmSummaryVirtualizeTests : BunitContext
Assert.Contains("Showing 20 of 20", cut.Markup);
}
/// <summary>Verifies that a long alarm list is virtualized and does not render every row.</summary>
[Fact]
public void LongList_VirtualizesWithoutRenderingEveryRow()
{
@@ -100,17 +102,22 @@ public class AlarmSummaryVirtualizeTests : BunitContext
/// <summary>Never goes live, so the page keeps its poll snapshot for these tests.</summary>
private sealed class InertLiveCache : ISiteAlarmLiveCache
{
/// <inheritdoc />
public IDisposable Subscribe(int siteId, Action onChanged) => new NoOp();
/// <inheritdoc />
public IReadOnlyList<AlarmStateChanged> GetCurrentAlarms(int siteId) =>
Array.Empty<AlarmStateChanged>();
/// <inheritdoc />
public bool IsLive(int siteId) => false;
/// <inheritdoc />
public IReadOnlyList<string> GetNotReportingInstances(int siteId) => Array.Empty<string>();
private sealed class NoOp : IDisposable
{
/// <summary>Does nothing; the no-op subscription holds no resources.</summary>
public void Dispose() { }
}
}
@@ -3,7 +3,7 @@ using ZB.MOM.WW.ScadaBridge.CentralUI.Components;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Monitoring;
/// <summary>
/// Regression tests for CentralUI-008. <c>&lt;input type="datetime-local"&gt;</c>
/// Regression tests for the datetime-local conversion. <c>&lt;input type="datetime-local"&gt;</c>
/// yields the value the user typed in their <i>browser-local</i> time zone. The
/// audit-log filter converted it with <c>new DateTimeOffset(value, TimeSpan.Zero)</c>
/// — relabelling the local wall-clock value as UTC, shifting the query window by
@@ -12,12 +12,14 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Monitoring;
/// </summary>
public class BrowserTimeTests
{
/// <summary>Verifies that local input to utc, when null, returns null.</summary>
[Fact]
public void LocalInputToUtc_Null_ReturnsNull()
{
Assert.Null(BrowserTime.LocalInputToUtc(null, 0));
}
/// <summary>Verifies that local input to utc, when utc browser, leaves time unchanged.</summary>
[Fact]
public void LocalInputToUtc_UtcBrowser_LeavesTimeUnchanged()
{
@@ -29,6 +31,7 @@ public class BrowserTimeTests
Assert.Equal(new DateTimeOffset(2026, 5, 16, 9, 30, 0, TimeSpan.Zero), utc);
}
/// <summary>Verifies that local input to utc, when positive utc offset browser, subtracts offset.</summary>
[Fact]
public void LocalInputToUtc_PositiveUtcOffsetBrowser_SubtractsOffset()
{
@@ -41,10 +44,11 @@ public class BrowserTimeTests
Assert.Equal(new DateTimeOffset(2026, 5, 16, 7, 30, 0, TimeSpan.Zero), utc);
}
/// <summary>Verifies that local input to utc, when negative utc offset browser, adds offset.</summary>
[Fact]
public void LocalInputToUtc_NegativeUtcOffsetBrowser_AddsOffset()
{
// A browser at UTC-5 (US Eastern, standard time) reports getTimezoneOffset() == 300.
// A browser at UTC minus 5 hours (US Eastern, standard time) reports getTimezoneOffset() == 300.
// The user typing 09:30 local means 14:30 UTC.
var local = new DateTime(2026, 5, 16, 9, 30, 0);
@@ -53,6 +57,7 @@ public class BrowserTimeTests
Assert.Equal(new DateTimeOffset(2026, 5, 16, 14, 30, 0, TimeSpan.Zero), utc);
}
/// <summary>Verifies that local input to utc, when non utc browser, does not equal naive relabelling.</summary>
[Fact]
public void LocalInputToUtc_NonUtcBrowser_DoesNotEqualNaiveRelabelling()
{
@@ -30,6 +30,7 @@ public class FailoverConfirmLabelTests : BunitContext
private readonly IManualFailoverService _failover = Substitute.For<IManualFailoverService>();
private readonly DialogService _dialog = new();
/// <summary>Initializes the bUnit context with an authenticated administrator and substitute failover service.</summary>
public FailoverConfirmLabelTests()
{
var claims = new[]
@@ -97,6 +98,8 @@ public class FailoverConfirmLabelTests : BunitContext
return host.FindAll("div.modal-footer button").ToList();
}
/// <summary>Verifies that the failover confirm button reads "Fail over" rather than "Delete".</summary>
/// <param name="siteId">The site id to fail over, or <see langword="null"/> for the central cluster.</param>
[Theory]
[InlineData(null)] // central pair
[InlineData("SiteA")] // site pair
@@ -111,6 +114,7 @@ public class FailoverConfirmLabelTests : BunitContext
Assert.Contains("Cancel", footerButtons);
}
/// <summary>Verifies that the failover confirm button keeps its destructive styling.</summary>
[Fact]
public void Failover_confirm_button_keeps_destructive_styling()
{
@@ -122,12 +126,14 @@ public class FailoverConfirmLabelTests : BunitContext
Assert.Contains("btn-danger", confirm.ClassList);
}
/// <summary>Verifies that a danger confirmation without a custom label still falls back to "Delete".</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task An_unlabelled_danger_confirm_still_falls_back_to_delete()
{
// The fallback is retained deliberately: ~20 genuine delete call sites rely
// on it (and the Playwright suites click the literal "Delete"). This pins that
// the row-28 fix is additive and did not change the default.
// the fail-over label fix is additive and did not change the default.
var cut = Render<DialogHost>();
await cut.InvokeAsync(() => { _ = _dialog.ConfirmAsync("Delete thing", "Sure?", danger: true); });
@@ -61,6 +61,7 @@ public class HealthFailoverButtonTests : BunitContext
return host.FindComponent<CentralFailoverControl>();
}
/// <summary>Verifies that the failover button is hidden for a non-admin user.</summary>
[Fact]
public void Button_is_hidden_for_a_non_admin()
{
@@ -71,6 +72,7 @@ public class HealthFailoverButtonTests : BunitContext
Assert.Empty(cut.FindAll("button"));
}
/// <summary>Verifies that the failover button is rendered and enabled for an admin when a standby node exists.</summary>
[Fact]
public void Button_is_rendered_and_enabled_for_an_admin_with_a_standby()
{
@@ -83,6 +85,7 @@ public class HealthFailoverButtonTests : BunitContext
Assert.Contains("failover", button.TextContent, StringComparison.OrdinalIgnoreCase);
}
/// <summary>Verifies that the failover button is disabled with an explanatory title when there is no standby.</summary>
[Fact]
public void Button_is_disabled_with_an_explanatory_title_when_there_is_no_standby()
{
@@ -96,6 +99,8 @@ public class HealthFailoverButtonTests : BunitContext
Assert.Contains("outage", button.GetAttribute("title"), StringComparison.OrdinalIgnoreCase);
}
/// <summary>Verifies that confirming the dialog triggers the failover exactly once.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Confirming_triggers_the_failover_exactly_once()
{
@@ -110,6 +115,8 @@ public class HealthFailoverButtonTests : BunitContext
await _failover.Received(1).FailOverCentralAsync("tester");
}
/// <summary>Verifies that cancelling the confirmation does not trigger a failover.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Cancelling_the_confirmation_does_not_trigger_a_failover()
{
@@ -122,6 +129,8 @@ public class HealthFailoverButtonTests : BunitContext
await _failover.DidNotReceive().FailOverCentralAsync(Arg.Any<string>());
}
/// <summary>Verifies that the confirmation warns that this page will disconnect.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Confirmation_warns_that_this_page_will_disconnect()
{
@@ -141,6 +150,8 @@ public class HealthFailoverButtonTests : BunitContext
Arg.Any<string?>());
}
/// <summary>Verifies that a refused failover surfaces the refusal instead of claiming success.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task A_refused_failover_surfaces_the_refusal_instead_of_claiming_success()
{
@@ -156,7 +167,7 @@ public class HealthFailoverButtonTests : BunitContext
Assert.Contains("no standby", cut.Markup, StringComparison.OrdinalIgnoreCase);
}
// ---- Site-pair failover (Task 10) ------------------------------------------
// ---- Site-pair failover ------------------------------------------
// Same control, SiteId set. The differences that matter: it calls the site path,
// and its confirmation must NOT claim the admin's own page will drop (it won't —
// the site is a different cluster).
@@ -175,6 +186,8 @@ public class HealthFailoverButtonTests : BunitContext
return host.FindComponent<CentralFailoverControl>();
}
/// <summary>Verifies that confirming on the site card triggers the site failover path.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Site_card_confirming_triggers_the_site_failover_path()
{
@@ -190,6 +203,8 @@ public class HealthFailoverButtonTests : BunitContext
await _failover.DidNotReceive().FailOverCentralAsync(Arg.Any<string>());
}
/// <summary>Verifies that the site card confirmation does not claim that this page will disconnect.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Site_card_confirmation_does_not_claim_this_page_disconnects()
{
@@ -210,6 +225,8 @@ public class HealthFailoverButtonTests : BunitContext
Arg.Any<string?>());
}
/// <summary>Verifies that the site card surfaces a refusal from the site.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Site_card_surfaces_a_refusal_from_the_site()
{
@@ -225,6 +242,8 @@ public class HealthFailoverButtonTests : BunitContext
Assert.Contains("No standby available", cut.Markup);
}
/// <summary>Verifies that the site card reports an unreachable site distinctly from a refusal.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Site_card_surfaces_an_unreachable_site_distinctly_from_a_refusal()
{
@@ -5,7 +5,7 @@ using ZB.MOM.WW.ScadaBridge.Security;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Monitoring;
/// <summary>
/// Regression tests for CentralUI-007. The design doc classifies the Site Event
/// Regression tests for page authorization. The design doc classifies the Site Event
/// Log Viewer and Parked Message Management as <b>Deployment Role</b>, but both
/// pages were annotated only <c>[Authorize]</c> (any authenticated user) — a
/// non-Deployment user who followed the nav link could query event logs and
@@ -20,6 +20,7 @@ public class MonitoringAuthorizationTests
.Cast<AuthorizeAttribute>()
.FirstOrDefault();
/// <summary>Verifies that the event logs page requires the Deployment authorization policy.</summary>
[Fact]
public void EventLogsPage_RequiresDeploymentPolicy()
{
@@ -29,6 +30,7 @@ public class MonitoringAuthorizationTests
Assert.Equal(AuthorizationPolicies.RequireDeployment, attr!.Policy);
}
/// <summary>Verifies that the parked messages page requires the Deployment authorization policy.</summary>
[Fact]
public void ParkedMessagesPage_RequiresDeploymentPolicy()
{
@@ -38,6 +40,7 @@ public class MonitoringAuthorizationTests
Assert.Equal(AuthorizationPolicies.RequireDeployment, attr!.Policy);
}
/// <summary>Verifies that the health dashboard is intentionally open to all authenticated roles.</summary>
[Fact]
public void HealthDashboard_IsIntentionallyAllAuthenticatedRoles()
{