fix(centralui): single relay toast, paging/skip polish, extra Site Calls tests
This commit is contained in:
@@ -15,6 +15,13 @@
|
||||
<PackageReference Include="Microsoft.Playwright" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" />
|
||||
<!--
|
||||
SkippableFact lets the Site Calls E2E tests report as Skipped (not Failed)
|
||||
when the dev cluster / MSSQL is not running. xunit 2.9.x does not ship
|
||||
Assert.Skip / SkipUnless — those are v3-only — so we use the canonical
|
||||
community wrapper, matching ScadaLink.ConfigurationDatabase.Tests.
|
||||
-->
|
||||
<PackageReference Include="Xunit.SkippableFact" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Playwright;
|
||||
using Xunit;
|
||||
|
||||
namespace ScadaLink.CentralUI.PlaywrightTests.SiteCalls;
|
||||
|
||||
@@ -27,8 +28,16 @@ namespace ScadaLink.CentralUI.PlaywrightTests.SiteCalls;
|
||||
/// Audit Log pre-filtered to the call's TrackedOperationId.</item>
|
||||
/// <item><c>RetryDiscardVisibility</c> — Retry/Discard appear only on Parked
|
||||
/// rows, never on Failed (or other) rows.</item>
|
||||
/// <item><c>RetryClickThrough</c> — clicking Retry on a Parked row confirms
|
||||
/// the dialog, relays to the owning site, and surfaces an outcome toast.</item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// The DB-seeding tests are <see cref="SkippableFactAttribute"/> + <c>Skip.IfNot</c>:
|
||||
/// when the cluster / MSSQL is unreachable they report as Skipped (not Failed),
|
||||
/// matching the established <c>ScadaLink.ConfigurationDatabase.Tests</c> idiom.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Collection("Playwright")]
|
||||
public class SiteCallsPageTests
|
||||
@@ -55,15 +64,15 @@ public class SiteCallsPageTests
|
||||
await Assertions.Expect(page.Locator("[data-test='site-calls-query']")).ToBeVisibleAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
/// <summary>Skip reason shared by the DB-seeding tests when MSSQL is down.</summary>
|
||||
private const string DbUnavailableSkipReason =
|
||||
"SiteCallDataSeeder cannot reach MSSQL at localhost:1433 — bring up infra/docker-compose and docker/deploy.sh, " +
|
||||
"or set SCADALINK_PLAYWRIGHT_DB to a reachable connection string.";
|
||||
|
||||
[SkippableFact]
|
||||
public async Task FilterNarrowing_ChannelFilterShrinksGrid()
|
||||
{
|
||||
if (!await SiteCallDataSeeder.IsAvailableAsync())
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"SiteCallDataSeeder cannot reach MSSQL at localhost:1433 — bring up infra/docker-compose and docker/deploy.sh, " +
|
||||
"or set SCADALINK_PLAYWRIGHT_DB to a reachable connection string.");
|
||||
}
|
||||
Skip.IfNot(await SiteCallDataSeeder.IsAvailableAsync(), DbUnavailableSkipReason);
|
||||
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/sc-filter/{runId}/";
|
||||
@@ -112,13 +121,10 @@ public class SiteCallsPageTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkippableFact]
|
||||
public async Task DrillIn_ViewAuditHistory_NavigatesToPreFilteredAuditLog()
|
||||
{
|
||||
if (!await SiteCallDataSeeder.IsAvailableAsync())
|
||||
{
|
||||
throw new InvalidOperationException("MSSQL unavailable; see FilterNarrowing test for setup instructions.");
|
||||
}
|
||||
Skip.IfNot(await SiteCallDataSeeder.IsAvailableAsync(), DbUnavailableSkipReason);
|
||||
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/sc-drill-in/{runId}/";
|
||||
@@ -162,13 +168,10 @@ public class SiteCallsPageTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[SkippableFact]
|
||||
public async Task RetryDiscard_VisibleOnlyOnParkedRows()
|
||||
{
|
||||
if (!await SiteCallDataSeeder.IsAvailableAsync())
|
||||
{
|
||||
throw new InvalidOperationException("MSSQL unavailable; see FilterNarrowing test for setup instructions.");
|
||||
}
|
||||
Skip.IfNot(await SiteCallDataSeeder.IsAvailableAsync(), DbUnavailableSkipReason);
|
||||
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/sc-actions/{runId}/";
|
||||
@@ -221,4 +224,59 @@ public class SiteCallsPageTests
|
||||
await SiteCallDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task RetryClickThrough_OnParkedRow_ConfirmsRelayAndShowsOutcomeToast()
|
||||
{
|
||||
Skip.IfNot(await SiteCallDataSeeder.IsAvailableAsync(), DbUnavailableSkipReason);
|
||||
|
||||
var runId = Guid.NewGuid().ToString("N");
|
||||
var targetPrefix = $"playwright-test/sc-retry-click/{runId}/";
|
||||
var parkedId = Guid.NewGuid();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
// A single Parked row — the only status from which Retry/Discard can
|
||||
// be relayed to the owning site.
|
||||
await SiteCallDataSeeder.InsertSiteCallAsync(
|
||||
trackedOperationId: parkedId, channel: "ApiOutbound", target: targetPrefix + "parked",
|
||||
sourceSite: "plant-a", status: "Parked", retryCount: 3,
|
||||
lastError: "HTTP 503 from ERP", httpStatus: 503,
|
||||
createdAtUtc: now, updatedAtUtc: now);
|
||||
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}{SiteCallsUrl}");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
await page.Locator("#sc-search").FillAsync(targetPrefix + "parked");
|
||||
await page.Locator("[data-test='site-calls-query']").ClickAsync();
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
var parkedRow = page.Locator("tbody tr", new() { HasText = targetPrefix + "parked" });
|
||||
await Assertions.Expect(parkedRow).ToBeVisibleAsync();
|
||||
|
||||
// Click Retry — this opens the confirmation dialog (DialogHost modal).
|
||||
await parkedRow.Locator("button:has-text('Retry')").ClickAsync();
|
||||
|
||||
// Confirm the relay in the dialog footer ("Confirm" — the non-danger
|
||||
// label; Discard would render "Delete").
|
||||
var confirmButton = page.Locator(".modal-footer button:has-text('Confirm')");
|
||||
await Assertions.Expect(confirmButton).ToBeVisibleAsync();
|
||||
await confirmButton.ClickAsync();
|
||||
|
||||
// The relay outcome surfaces on a toast — Applied, NotParked or, if
|
||||
// the owning site is offline in this environment, SiteUnreachable.
|
||||
// We only assert that an outcome toast appears (exactly one — the
|
||||
// single-toast contract), not which one, since the live cluster
|
||||
// state determines the outcome.
|
||||
var toast = page.Locator(".toast");
|
||||
await Assertions.Expect(toast).ToBeVisibleAsync();
|
||||
Assert.Equal(1, await toast.CountAsync());
|
||||
}
|
||||
finally
|
||||
{
|
||||
await SiteCallDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user