513fa1aa16
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.
133 lines
6.0 KiB
C#
133 lines
6.0 KiB
C#
using Bunit;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
|
|
|
|
/// <summary>
|
|
/// Deferred-work register row 75 — pins the confirm button's severity → Bootstrap class
|
|
/// mapping against the REAL <see cref="DialogService"/> behind a real <c>DialogHost</c>,
|
|
/// so these cover what the user actually sees rather than what an argument was.
|
|
///
|
|
/// <para>
|
|
/// Row 28 split the label from the styling but left the styling a two-state boolean, so a
|
|
/// consequential-but-not-destructive action had to choose between looking like a delete
|
|
/// and looking like the safe default. Row 75 added <see cref="DialogSeverity.Caution"/> as
|
|
/// the middle rung. The three-way mapping is the whole of that change, and these are its
|
|
/// pins; <c>SecuredWritesTests</c> separately pins that the Secured Writes page asks for
|
|
/// the right one.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// bUnit cannot run real JS interop, so the host's <c>sbDialog.*</c> focus-trap calls run
|
|
/// in <see cref="JSRuntimeMode.Loose"/> as no-ops (same arrangement as
|
|
/// <c>FailoverConfirmLabelTests</c>).
|
|
/// </para>
|
|
/// </summary>
|
|
public class DialogSeverityStylingTests : BunitContext
|
|
{
|
|
private readonly DialogService _dialog = new();
|
|
|
|
/// <summary>Initializes the test context with the dialog service and its dependencies.</summary>
|
|
public DialogSeverityStylingTests()
|
|
{
|
|
Services.AddSingleton<IDialogService>(_dialog);
|
|
JSInterop.Mode = JSRuntimeMode.Loose;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens a confirm dialog on a live host and returns its confirm button.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The <c>ConfirmAsync</c> task is deliberately not awaited — with the real service it
|
|
/// does not complete until someone answers the dialog, so awaiting it would deadlock
|
|
/// the test. The state is published synchronously before the task is returned.
|
|
/// </remarks>
|
|
private AngleSharp.Dom.IElement OpenConfirm(Func<IDialogService, Task<bool>> open)
|
|
{
|
|
var cut = Render<DialogHost>();
|
|
cut.InvokeAsync(() => { _ = open(_dialog); }).GetAwaiter().GetResult();
|
|
cut.Render();
|
|
|
|
var footer = cut.FindAll("div.modal-footer button").ToList();
|
|
return footer.Single(b => b.TextContent.Trim() != "Cancel");
|
|
}
|
|
|
|
/// <summary>Verifies that a caution dialog renders amber, neither red nor primary.</summary>
|
|
[Fact]
|
|
public void Caution_rendersAmber_notRedAndNotPrimary()
|
|
{
|
|
// The caution case. Amber is the point: not red (which reads "delete"), and not
|
|
// the primary blue (which reads "safe default" — wrong for a live device write).
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Approve thing", "Sure?", DialogSeverity.Caution, "Approve"));
|
|
|
|
Assert.Contains("btn-warning", confirm.ClassList);
|
|
Assert.DoesNotContain("btn-danger", confirm.ClassList);
|
|
Assert.DoesNotContain("btn-primary", confirm.ClassList);
|
|
}
|
|
|
|
/// <summary>Verifies that a destructive dialog still renders red.</summary>
|
|
[Fact]
|
|
public void Destructive_stillRendersRed()
|
|
{
|
|
// Regression guard on the ~20 genuine delete call sites: row 75 is additive and
|
|
// must not have shifted what danger looks like.
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Delete thing", "Sure?", DialogSeverity.Destructive));
|
|
|
|
Assert.Contains("btn-danger", confirm.ClassList);
|
|
}
|
|
|
|
/// <summary>Verifies that a normal dialog still renders with the primary style.</summary>
|
|
[Fact]
|
|
public void Normal_stillRendersPrimary()
|
|
{
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Do thing", "Sure?", DialogSeverity.Normal));
|
|
|
|
Assert.Contains("btn-primary", confirm.ClassList);
|
|
}
|
|
|
|
/// <summary>Verifies that the boolean danger form maps onto the same two severities.</summary>
|
|
/// <param name="danger">Whether the dialog is requested as dangerous.</param>
|
|
/// <param name="expectedClass">The button CSS class the dialog is expected to render.</param>
|
|
[Theory]
|
|
[InlineData(true, "btn-danger")]
|
|
[InlineData(false, "btn-primary")]
|
|
public void BooleanForm_mapsOntoTheSameTwoSeverities(bool danger, string expectedClass)
|
|
{
|
|
// The boolean overload is now a thin adapter onto the severity one. Every existing
|
|
// call site goes through it, so this pins that the adapter did not shift any of
|
|
// them: true is still red, false is still primary.
|
|
//
|
|
// One case per fact, deliberately: DialogService permits only one open dialog at a
|
|
// time and throws on the second, so two OpenConfirm calls in one body would fail
|
|
// on the service's own nested-dialog guard rather than on anything about styling.
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Do thing", "Sure?", danger: danger));
|
|
|
|
Assert.Contains(expectedClass, confirm.ClassList);
|
|
}
|
|
|
|
/// <summary>Verifies that a caution dialog without a label reads Confirm rather than Delete.</summary>
|
|
[Fact]
|
|
public void UnlabelledCaution_readsConfirm_notDelete()
|
|
{
|
|
// Caution deliberately does NOT inherit the danger "Delete" fallback: a caution
|
|
// action is by definition not a delete, so falling back to that verb would
|
|
// reintroduce register row 28 through the new door.
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Approve thing", "Sure?", DialogSeverity.Caution));
|
|
|
|
Assert.Equal("Confirm", confirm.TextContent.Trim());
|
|
}
|
|
|
|
/// <summary>Verifies that a destructive dialog without a label still falls back to Delete.</summary>
|
|
[Fact]
|
|
public void UnlabelledDestructive_stillFallsBackToDelete()
|
|
{
|
|
// The "Delete" fallback is retained deliberately (the Playwright suites click the
|
|
// literal "Delete"). Pinned here alongside its new sibling so the pair is read
|
|
// together.
|
|
var confirm = OpenConfirm(d => d.ConfirmAsync("Delete thing", "Sure?", DialogSeverity.Destructive));
|
|
|
|
Assert.Equal("Delete", confirm.TextContent.Trim());
|
|
}
|
|
}
|