fix(admin-e2e): register missing DI services so ClusterDetail interactive circuit boots
UnsTabDragDropE2ETests were timing out at the 'UNS Structure' nav-link locator because AdminWebAppFactory never registered AdminHubConnectionFactory / HubTokenService / DataProtection — ClusterDetail.razor's @inject threw at circuit boot, so the page never advanced past the Loading placeholder. 2 → 3 pass after the registrations land. Also documents the Modbus standard-vs- exception_injection coverage matrix in the fixture README + cross-references docs/drivers/AbServer-Test-Fixture.md from each Emulate test so a developer landing on a skipped test has a direct doc pointer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,10 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests.Emulate;
|
|||||||
/// <para>Runs only when <c>AB_SERVER_PROFILE=emulate</c>. ab_server has no ALMD
|
/// <para>Runs only when <c>AB_SERVER_PROFILE=emulate</c>. ab_server has no ALMD
|
||||||
/// instruction + no alarm subsystem, so this tier-gated class couldn't produce a
|
/// instruction + no alarm subsystem, so this tier-gated class couldn't produce a
|
||||||
/// meaningful result against the default simulator.</para>
|
/// meaningful result against the default simulator.</para>
|
||||||
|
/// <para>The Emulate tier is hardware-gated (Rockwell per-seat license, Windows-only,
|
||||||
|
/// conflicts with Docker Desktop's WSL 2 backend) so a permanent skip in CI is expected
|
||||||
|
/// — see <c>docs/drivers/AbServer-Test-Fixture.md</c> §"Logix Emulate golden-box tier"
|
||||||
|
/// for the full rationale + the gap matrix this test closes.</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Collection("AbServerEmulate")]
|
[Collection("AbServerEmulate")]
|
||||||
[Trait("Category", "Integration")]
|
[Trait("Category", "Integration")]
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests.Emulate;
|
|||||||
/// <para>Runs only when <c>AB_SERVER_PROFILE=emulate</c>. With ab_server
|
/// <para>Runs only when <c>AB_SERVER_PROFILE=emulate</c>. With ab_server
|
||||||
/// (the default), skips cleanly — ab_server lacks UDT / Template Object emulation
|
/// (the default), skips cleanly — ab_server lacks UDT / Template Object emulation
|
||||||
/// so this wire-level test couldn't pass against it regardless.</para>
|
/// so this wire-level test couldn't pass against it regardless.</para>
|
||||||
|
/// <para>The Emulate tier is hardware-gated (Rockwell per-seat license, Windows-only,
|
||||||
|
/// conflicts with Docker Desktop's WSL 2 backend) so a permanent skip in CI is expected
|
||||||
|
/// — see <c>docs/drivers/AbServer-Test-Fixture.md</c> §"Logix Emulate golden-box tier"
|
||||||
|
/// for the full rationale + the gap matrix this test closes.</para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Collection("AbServerEmulate")]
|
[Collection("AbServerEmulate")]
|
||||||
[Trait("Category", "Integration")]
|
[Trait("Category", "Integration")]
|
||||||
|
|||||||
@@ -48,6 +48,23 @@ service + starting another. The integration tests discriminate by a
|
|||||||
separate `MODBUS_SIM_PROFILE` env var so they skip correctly when the
|
separate `MODBUS_SIM_PROFILE` env var so they skip correctly when the
|
||||||
wrong profile is live.
|
wrong profile is live.
|
||||||
|
|
||||||
|
### Profile coverage matrix
|
||||||
|
|
||||||
|
The two general-purpose profiles cover disjoint test sets. A full pass
|
||||||
|
of the integration suite requires running both — serially on a single
|
||||||
|
docker host (the `:5020` collision), or in parallel on two hosts.
|
||||||
|
|
||||||
|
| Job | Bring up | Env to set | Expected outcome |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `modbus-standard` | `lmxopcua-fix up modbus standard` | unset `MODBUS_SIM_PROFILE` (or set to `standard`) | Standard round-trip + AddressingGrammar suites pass; `ExceptionInjectionTests` (32 rows) skip with `MODBUS_SIM_PROFILE != exception_injection`. |
|
||||||
|
| `modbus-exception` | `lmxopcua-fix up modbus exception_injection` | `MODBUS_SIM_PROFILE=exception_injection` | `ExceptionInjectionTests` (32 rows) pass against the per-`(fc,address)` rule set; standard-profile suites (round-trip, AddressingGrammar) skip. |
|
||||||
|
|
||||||
|
The DL205 / Mitsubishi / S7-1500 profiles are similar — each gates its
|
||||||
|
own quirks suite via `MODBUS_SIM_PROFILE=<profile>`. Tests that don't
|
||||||
|
need a specific profile (the basic round-trip set) run under any of
|
||||||
|
the three pymodbus-based profiles. The `exception_injection` profile
|
||||||
|
is the only one that runs `exception_injector.py` instead of pymodbus.
|
||||||
|
|
||||||
## Endpoint
|
## Endpoint
|
||||||
|
|
||||||
- Default: `localhost:5020`
|
- Default: `localhost:5020`
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using ZB.MOM.WW.OtOpcUa.Admin.Hubs;
|
using ZB.MOM.WW.OtOpcUa.Admin.Hubs;
|
||||||
|
using ZB.MOM.WW.OtOpcUa.Admin.Security;
|
||||||
using ZB.MOM.WW.OtOpcUa.Configuration;
|
using ZB.MOM.WW.OtOpcUa.Configuration;
|
||||||
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||||
@@ -101,6 +102,15 @@ public sealed class AdminWebAppFactory : IAsyncDisposable
|
|||||||
builder.Services.AddScoped<Admin.Services.DriverInstanceService>();
|
builder.Services.AddScoped<Admin.Services.DriverInstanceService>();
|
||||||
builder.Services.AddScoped<Admin.Services.DraftValidationService>();
|
builder.Services.AddScoped<Admin.Services.DraftValidationService>();
|
||||||
|
|
||||||
|
// ClusterDetail.razor injects AdminHubConnectionFactory to drive the live-banner hub
|
||||||
|
// connection; the factory depends on HubTokenService, which in turn needs Data Protection.
|
||||||
|
// Without these the InteractiveServer circuit fails to instantiate the component and the
|
||||||
|
// page never advances past the "Loading…" placeholder — Playwright then times out
|
||||||
|
// waiting for any tab nav-link to appear. Mirrors Program.cs:35-36.
|
||||||
|
builder.Services.AddDataProtection();
|
||||||
|
builder.Services.AddSingleton<HubTokenService>();
|
||||||
|
builder.Services.AddScoped<Admin.Services.AdminHubConnectionFactory>();
|
||||||
|
|
||||||
_app = builder.Build();
|
_app = builder.Build();
|
||||||
_app.UseStaticFiles();
|
_app.UseStaticFiles();
|
||||||
_app.UseRouting();
|
_app.UseRouting();
|
||||||
|
|||||||
Reference in New Issue
Block a user