Hexalith.FrontComposer.Testing
4.7.0
dotnet add package Hexalith.FrontComposer.Testing --version 4.7.0
NuGet\Install-Package Hexalith.FrontComposer.Testing -Version 4.7.0
<PackageReference Include="Hexalith.FrontComposer.Testing" Version="4.7.0" />
<PackageVersion Include="Hexalith.FrontComposer.Testing" Version="4.7.0" />
<PackageReference Include="Hexalith.FrontComposer.Testing" />
paket add Hexalith.FrontComposer.Testing --version 4.7.0
#r "nuget: Hexalith.FrontComposer.Testing, 4.7.0"
#:package Hexalith.FrontComposer.Testing@4.7.0
#addin nuget:?package=Hexalith.FrontComposer.Testing&version=4.7.0
#tool nuget:?package=Hexalith.FrontComposer.Testing&version=4.7.0
Hexalith.FrontComposer.Testing
Adopter-facing test utilities for rendering generated FrontComposer components with bUnit.
Commands support deterministic success, rejection, immediate timeout, and stall-at-Syncing. Each test host emits the same canonical ULID sequence from a fresh instance, with distinct message and correlation identifiers for every dispatch. Queries and pages accept per-request callbacks with last-write-wins configuration. TestAuthorizationEvaluator is registered as the exact evaluator exposed by the host and fails closed for unknown policies.
TestFaultEvidenceRecorder records bounded, redacted scenario evidence only; it does not inject transport behavior. Use AddFrontComposerTestHostAsync(...) for DuringHostSetup store initialization and pass its optional cancellation token when test setup is cancelable. The synchronous API rejects that mode instead of blocking on async work.
Use FrontComposerTestBase for inheritance-based tests, or call Services.AddFrontComposerTestHost(...) from a BunitContext for composition-based setup. Dispose the returned FrontComposerTestHostBuilder when composing directly so culture settings are restored. The package registers in-memory storage, deterministic tenant and user context, Shell services, command/query/page-loader fakes, loose JS interop defaults, and component assertion helpers without requiring a running app host.
The deterministic fakes are per test host instance. TestCommandService captures redacted dispatch evidence and lifecycle states, TestQueryService supports success and not-modified paths through SucceedWith<T>() and NotModifiedWith<T>(), and TestProjectionPageLoader supports configured pages plus not-modified evidence.
Evidence formatting redacts configured tenant/user values and token, secret, password, authorization, API-key, cookie, private-key, or connection-string keyed values before truncation and assertion output. Cyclic, unsupported, or throwing payloads produce a bounded <serialization-unavailable> marker without changing the configured command outcome; process-fatal exceptions still propagate. The package public surface is pinned by PublicAPI.Shipped.txt; update that baseline intentionally when adding adopter-facing APIs.
Deterministic UX assertions
Set FrontComposerTestOptions.TimeProvider to a TestTimeProvider. Its UTC clock, monotonic timestamp, one-shot timers, periodic timers, Change, and disposal advance synchronously without sleeping. Timer callbacks run outside the clock lock and use their creation execution context. Advance the clock on the component dispatcher when a timer changes rendered state. It intentionally does not drain arbitrary asynchronous work; await the operation or renderer explicitly.
UxTiming exposes canonical default budgets, including 250 ms coalescing/post-accept retry, 2 s SlowQuery, 3 s recovery notice, 10 s degradation/fresh-row lifetime, 1 s status polls, 15 s projection polls, 30 s retry cap, and the 120 s polling ceiling. UxTimingAssertions.AssertBoundary checks N-1 ms and N ms from the operation start. The consumer suite compares these defaults with Shell options and internal constants; adopter overrides do not change the canonical defaults.
| Canonical matrix | Adopter helper |
|---|---|
| AM-01..31 | UxAnnouncementCatalog.Expected resolves Shell resource copy by row and culture; operation and state identities remain separate from copy. AM-26 requires a supported heading resource key; AM-30 accepts variant: "offline"; AM-18/19 accept variant: "single". |
| AM sequence and silence | AssertSequence checks exact order/count/copy/channel/operation/state; an empty expected list asserts silence. AssertDistinctChannels rejects duplicate speech for one event and conflicting lifecycle terminal outcomes for one operation, including Confirmed/IdempotentConfirmed. Diagnostics omit observed text and opaque identifiers. |
| AM coalescing and cancellation | AssertCoalescingBoundary advances 249/250 ms after the last eligible change. AssertImmediateCancellation checks the decisive event immediately and again after the pending window. Include all observed events, including stale-result and silent-expiry drift. |
| AM channel ownership | AssertChannel checks role/name, live attributes, atomic palette ownership, and focus-only summary/heading. Supply the measured speech-owner count and inherited result-count count; the helper cannot discover browser nodes. |
| VR-01/02 and preservation | UxValidationAssertions.AssertLinkedSummary compares measured summary text/count separately from its accessible label, checks invalid-only links in complete declared order, verifies declared group membership/name/description against measured relationships, and compares control/error targets with prior-render identities. Visible labels may appear inside richer accessible names. AssertInputPreserved compares useful values without printing them. |
| SS-01..49 and VR-05 | UxStateAssertions.AssertState checks canonical state names, subject terminality, and required caller-measured UxSurfaceFacts for tabs/panels, failure/no-success truth, polling and non-live/focus behavior; command states retain machine identity, including IdempotentConfirmed and DegradedExhausted. AssertBlockedSubmit also checks did-not-run copy, one event, retained focus, and no dispatch/queue. |
| OF-01..04 and FM-04/05/11 | UxFocusAssertions.CaptureOrigin captures the direct element handle before activation plus optional contract locator. AssertRestored uses reference identity, connected/enabled/visible status, and route-h1 or form-heading fallback. |
| AE-05 and FM geometry | AssertUnobscured checks full target and painted focus bounds against every viewport/scrollport and all app-owned occluders. Supply computed paint bounds, including pseudo-elements, outline and shadows; a target rectangle alone cannot prove focus-indicator visibility. |
| AE-01..09 | TestAccessibilityEvidenceRecorder uses the configured clock, bounded record retention, and the shared redactor. Pass an AccessibilityEvidenceContext with positive surface/state inventory ordinals and a typed UxTheme. Its sealed AccessibilityMeasurements schema retains dimension-specific setup and observed loss, clipping, overlap, truncation, forced-color cue survival, animation suppression, silent expiry, keyboard/axe outcomes and geometry without arbitrary text. Missing measurements for the recorded row fail explicitly; failed measurements remain recordable. UxAccessibilityAssertions.AssertTargetSize checks 24×24 CSS px or one evidenced exception. |
Measurement and accessibility snapshots are caller-supplied, so these APIs require no browser library or TypeScript distribution. Resolve roles and accessible names first; data-testid is a supplementary evidence locator. Keep the full observation sequence instead of pre-filtering unexpected messages.
For target-size exceptions, record target ordinals, exactly one UxTargetSizeExceptionKind, its UxTargetSizeRationale, the keyboard key path, neighboring bounds for Spacing, or a separate conforming equivalent-control ordinal and bounds for Equivalent. The fixed schema excludes credentials, AX names, tenant payloads, backend metadata, stack traces, and personal text. Do not encode identifiers in numeric measurement fields. Increase MaxDiagnosticPayloadCharacters when a complete structured measurement packet is needed; truncation remains explicit.
These helpers record automated evidence only. They do not replace required manual assistive-technology/device evidence or close OI-16, G-4, FLUENT-APP-1, or Product approval.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AngleSharp (>= 1.8.5)
- bunit (>= 2.11.3)
- Hexalith.FrontComposer.Contracts (>= 4.7.0)
- Hexalith.FrontComposer.Shell (>= 4.7.0)
- Microsoft.AspNetCore.Authentication.OpenIdConnect (>= 10.0.13)
- Microsoft.AspNetCore.Components.WebAssembly (>= 10.0.13)
- Microsoft.AspNetCore.Components.WebAssembly.Authentication (>= 10.0.13)
- Microsoft.AspNetCore.SignalR.Client (>= 10.0.13)
- Microsoft.FluentUI.AspNetCore.Components (>= 5.0.1)
- Microsoft.FluentUI.AspNetCore.Components.Icons (>= 5.0.1)
- Microsoft.IdentityModel.Abstractions (>= 8.23.0)
- Microsoft.IdentityModel.JsonWebTokens (>= 8.23.0)
- Microsoft.IdentityModel.Logging (>= 8.23.0)
- Microsoft.IdentityModel.Protocols (>= 8.23.0)
- Microsoft.IdentityModel.Protocols.OpenIdConnect (>= 8.23.0)
- Microsoft.IdentityModel.Tokens (>= 8.23.0)
- NUlid (>= 1.7.3)
- System.IdentityModel.Tokens.Jwt (>= 8.23.0)
- System.Reactive (>= 7.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.7.0 | 176 | 10/18/2026 |
| 4.6.0 | 1,041 | 10/5/2026 |
| 4.5.0 | 1,027 | 9/19/2026 |
| 4.4.0 | 662 | 9/7/2026 |
| 4.3.0 | 256 | 9/5/2026 |
| 4.2.0 | 184 | 8/30/2026 |
| 4.1.1 | 703 | 8/6/2026 |
| 4.1.0 | 100 | 8/6/2026 |
| 4.0.1 | 416 | 7/16/2026 |
| 4.0.0 | 92 | 7/15/2026 |
| 3.2.2 | 117 | 7/14/2026 |
| 3.2.1 | 90 | 7/14/2026 |
| 3.2.0 | 86 | 7/14/2026 |
| 3.1.1 | 88 | 7/14/2026 |
| 3.1.0 | 94 | 7/14/2026 |
| 3.0.0 | 250 | 7/14/2026 |
| 2.0.4 | 128 | 7/12/2026 |
| 2.0.3 | 95 | 7/12/2026 |
| 2.0.2 | 89 | 7/12/2026 |
| 2.0.1 | 85 | 7/12/2026 |