Validate audit windows and isolate dashboard count reads

This commit is contained in:
Joseph Doherty
2026-11-13 18:23:12 -05:00
parent 102cbb2e90
commit 2d30323ae8
55 changed files with 11250 additions and 79 deletions
@@ -63,3 +63,29 @@ Parent review found the raw-JSON escape-hatch error was not described by its com
Commit915a8a59 was created before the author checked the focused result carefully. Its raw-json-association-green.log actually contains98 passes/1 failure and remains unchanged as historical evidence. The fixture incorrectly expected valid JSON object syntax to erase the existing unresolved-schema error. This was a test-premise error; production validation must retain that error.
The corrected regression now asserts invalid syntax is linked, valid object syntax still retains the unknown-declared-type error, and then valid JSON null clears invalidity under InboundApiSchema's existing explicit present-null-is-allowed contract. All prior relationship/domain-name assertions remain. No production source or validator changed in this correction. Focused ParameterValueForm/Monaco/TreeView result:99/99 passed, zero skips/failures (raw-json-association-corrected-green.log). Parent accepted focused verification after the prior1559 full baseline. This paragraph supersedes the premature green claim above; it does not rewrite the red evidence.
## SB04–06 review batch
SB04's UTC-labelled native inputs now belong to AuditFilterBar. The reusable DateTimeRangeFilter remains unchanged: its DateTime? callback intentionally cannot distinguish invalid raw text from an empty bound. The parent approved using its same native two-field geometry/labels locally so the audit caller can keep correction strings. Valid literals are tagged UTC without browser/server-zone conversion, including DST-date literals. Intentional nullable bounds remain supported; invalid/inverted input returns before OnFilterChanged, preserves strings, and links a recovery error. The query model, presets, filters and backend remain unchanged. New error uses shared field-error s-bad (#b42121), not a local color override. Clear resets raw strings/error together with existing model reset.
SB05 dashboard facts settle independently after each read with individual loading/known-zero/unavailable state. Repository reads remain sequential because some adapters share one scoped DbContext. A failed read does not block later reads or replace available facts. Each named region's Retry calls only its read. No domain service, aggregation, polling or authorization change. SB08/SB10/SB11 still own dashboard hierarchy, destination policy and operational-summary changes.
SB06 adds contextual Dismiss [title] names to toast close controls and preserves timing/live-region/disposal behavior. Two-toast test proves one dismissal preserves the other message.
Evidence sb04-06: red-utc-toast.log6 intended failures; red-dashboard.log6 intended failures. Full Release suite1575/1575 passed, zero skips/failures (full-suite.log/sb04-06.trx). Final audit tests20/20 pass under UTC, America/Indianapolis and Asia/Tokyo; custom, DST, invalid/inverted, correction, nullable and existing preset/filter cases remain green. Only a shared semantic error class and stronger false-zero assertion followed the full run; final-focused.log covers the final audit/dashboard/toast state.
First8-case browser matrix retained in browser/results.json. UTC literals/inverted guards passed all4 cases (New_York/Tokyo browser zones ×1440/390). Immediate dashboard retry and one toast count were read before InteractiveServer completion and reported false. The retained confirmation adds outcome-based waits; no source state logic changed for these measurement failures. An intermediate harness quoting typo is retained as confirmation-harness-error.log. Final bounded confirmation8/8 passes (browser-confirmation/results.json): same UTC boundaries, input text retained on inverted range, partial-dashboard Unavailable→known-zero retry with successful facts retained, and named target-only dismissal. All captured dashboard/toast document widths equal viewport width; visual inspection confirms existing density and hierarchy are retained for later SB08 changes.
Fixture changes under umbrella validation/scadabridge-ui/host supply only empty read projections and one deliberate first API-key-read failure. All non-read operations reject; no Save/test-send/verify/trust/deploy was performed. Direct actual component composition does not establish application authentication or live backend behavior. Original G1 evidence is unchanged.
This batch's production scope is4 Razor/C# source files (AuditFilterBar pair, Dashboard, ToastNotification) plus3 test files; frozen hashes are sb04-06/source-freeze.json. No SB07+ source changes or batch commit before review.
### SB04–06 concrete peer corrections
The original bUnit invalid-string test did not prove native partial-date behavior. Actual Chromium keyboard entry reproduced value empty + badInput true and the prior onclick Apply emitted an unbounded filter (native-partial-before.json). AuditFilterBar now owns one native form; its only production callsite in AuditLogPage has no surrounding form. Apply submits, Clear is explicitly type=button, and native constraint validation blocks incomplete values before the Blazor submit handler. Tests submit the form instead of directly invoking a button click; all existing filter assertions remain. The input uses step=any to avoid unintentionally rejecting valid seconds. Intentionally cleared optional bounds remain accepted.
The native after proof uses actual segmented keyboard entry, not programmatic invalid value assignment: partial input is blocked, focus returns to From, then a genuinely cleared optional bound submits null. Explicit aria-invalid=false initially masked native badInput in Chromium AX. The caller now emits aria-invalid=true only for its own range errors and otherwise omits it; native AX reports invalid=true for a partial native date. Before/after AX proof is retained with native-partial-after.json and native-partial-aria-before.json. No JS validity workaround.
Dashboard initial reads alone were sequential, but an early Retry could overlap the next repository read. All initial/retry operations now share a component-owned async gate. The renderer claims each fact's pending state before its first await, coalescing duplicate target requests. A deterministic delayed-Connections/early-Sites-retry regression reproduces the prior3 Sites invocations before Connections completed (expected1); final code waits and makes exactly one recovery read. Counts remain independent, and successful facts are not reloaded. The first async test attempt had CS4014 in NSubstitute verification; compile output is preserved separately, then meaningful red/green evidence follows.
Reviewed full Release suite1576/1576 passed, zero skips/failures (reviewed-full-suite.log/sb04-06-reviewed.trx). The only following production change was omitting the false ARIA override; final focused31/31 and final20 audit cases in each of UTC/Indianapolis/Tokyo pass. Native Chromium focused after proof passes including AX invalid=true. These correction checks are narrow technical regressions, not another broad screenshot/polish round. No batch commit or SB07+ expansion until parent accepts the corrected frozen source.
@@ -0,0 +1,8 @@
# Read-only SB07–09 preflight
No SB07+ production edits during SB04–06 review.
- SB07: FlowDebugger/FlowGraphView/FlowTraceList scoped CSS still uses saturated --ok/--warn/--bad and mixed Bootstrap colors for text; replace foregrounds with shared inks, keep signal borders/dots. Current supported-dark aliases are already in site.css. Existing Bootstrap text utility use across field errors needs the same local host text bridge rather than repeated literal colors. Capture actual before pairs on a disposable synthetic flow/state fixture; CSS declaration tests are inappropriate. Existing FlowDebuggerPageTests/PendingUpdatesHealthTilesTests verify unchanged domain state and policy behavior.
- SB08: next-page-inventory.json gives44 page components/57 route declarations;42 lack h1 and5 table-dark occurrences. Promote existing first page titles while retaining their compact visual scale and factual text; use shared page-head. Conditional loading/error branches must still have one page title. Preserve all role checks/actions. Topology search/primary Instance/Refresh/Live update stay visible; move infrequent expand/collapse/recheck/Area actions into a native disclosure without changing their handlers. Existing first render title is inside the loaded branch, so the heading test must cover loading/error too if moving it out.
- SB09: shared DataTable footer currently says1–0 for empty results. Existing DataTablePagerTests supplies RenderTable(itemCount,pageSize), so add true-empty and filtered-to-empty regressions plus existing pagination coverage. Add named local overflow region/keyboard access and safe optional TableLabel. Source scan found no production page DataTable callsites; it remains a tested reusable component. Do not claim all manual page tables are fixed by that component change. Manual tables are in SB08 route inventory and need their own local wrappers/header parity.
- Source route/state semantics remain unchanged: topology loaded-only search/lazy loading/poll caps, flow predicted/live/replay state labels, completed step with error logs, auth gates and secure-write domain operations are not presentation cleanup targets.
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

@@ -0,0 +1,103 @@
{
"results": [
{
"sample": "audit",
"width": 1440,
"browserZone": "America/New_York",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
},
"errorColor": "rgb(180, 33, 33)"
},
{
"sample": "audit",
"width": 1440,
"browserZone": "Asia/Tokyo",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
},
"errorColor": "rgb(180, 33, 33)"
},
{
"sample": "dashboard",
"width": 1440,
"checks": {
"unavailableNotZero": true,
"retryKnownZero": true,
"otherFactsRemain": true
},
"layout": {
"innerWidth": 1440,
"scrollWidth": 1440
}
},
{
"sample": "toast",
"width": 1440,
"checks": {
"onlyTargetDismissed": true,
"otherDismissNamed": true
},
"layout": {
"innerWidth": 1440,
"scrollWidth": 1440
}
},
{
"sample": "audit",
"width": 390,
"browserZone": "America/New_York",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
},
"errorColor": "rgb(180, 33, 33)"
},
{
"sample": "audit",
"width": 390,
"browserZone": "Asia/Tokyo",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
},
"errorColor": "rgb(180, 33, 33)"
},
{
"sample": "dashboard",
"width": 390,
"checks": {
"unavailableNotZero": true,
"retryKnownZero": true,
"otherFactsRemain": true
},
"layout": {
"innerWidth": 390,
"scrollWidth": 390
}
},
{
"sample": "toast",
"width": 390,
"checks": {
"onlyTargetDismissed": true,
"otherDismissNamed": true
},
"layout": {
"innerWidth": 390,
"scrollWidth": 390
}
}
],
"passed": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

@@ -0,0 +1,99 @@
{
"results": [
{
"sample": "audit",
"width": 1440,
"browserZone": "America/New_York",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
}
},
{
"sample": "audit",
"width": 1440,
"browserZone": "Asia/Tokyo",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
}
},
{
"sample": "dashboard",
"width": 1440,
"checks": {
"unavailableNotZero": true,
"retryKnownZero": false,
"otherFactsRemain": true
},
"layout": {
"innerWidth": 1440,
"scrollWidth": 1440
}
},
{
"sample": "toast",
"width": 1440,
"checks": {
"onlyTargetDismissed": true,
"otherDismissNamed": true
},
"layout": {
"innerWidth": 1440,
"scrollWidth": 1440
}
},
{
"sample": "audit",
"width": 390,
"browserZone": "America/New_York",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
}
},
{
"sample": "audit",
"width": 390,
"browserZone": "Asia/Tokyo",
"utcResult": "From=2026-03-08T01:30:00.0000000Z;To=2026-03-08T02:30:00.0000000Z;FromKind=Utc;ToKind=Utc",
"checks": {
"literalUTC": true,
"invertedBlocked": true,
"correctionPreserved": true
}
},
{
"sample": "dashboard",
"width": 390,
"checks": {
"unavailableNotZero": true,
"retryKnownZero": false,
"otherFactsRemain": true
},
"layout": {
"innerWidth": 390,
"scrollWidth": 390
}
},
{
"sample": "toast",
"width": 390,
"checks": {
"onlyTargetDismissed": false,
"otherDismissNamed": true
},
"layout": {
"innerWidth": 390,
"scrollWidth": 390
}
}
],
"passed": false
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

@@ -0,0 +1,37 @@
Traceback (most recent call last):
File "/Users/dohertj2/Desktop/ScadaBridge/infra/tools/inspect_states_and_utc.py", line 15, in <module>
fact=page.locator('[role=region][aria-label="API keys"]');record['checks']['unavailableNotZero']='Unavailable' in fact.inner_text();page.get_by_role('button',name='Retry API keys',exact=True).click();page.wait_for_function('!document.querySelector("[role=region][aria-label=\"API keys\"]").textContent.includes("Unavailable") && !document.querySelector("[role=region][aria-label=\"API keys\"]").textContent.includes("Loading")');record['checks']['retryKnownZero']='0' in fact.inner_text() and 'Unavailable' not in fact.inner_text();record['checks']['otherFactsRemain']=all('0' in page.locator('[role=region][aria-label="'+label+'"]').inner_text() for label in ['Sites configured','Data connections configured','Templates'])
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.14/site-packages/playwright/sync_api/_generated.py", line 11599, in wait_for_function
self._sync(
~~~~~~~~~~^
self._impl_obj.wait_for_function(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<4 lines>...
)
^
)
^
File "/opt/homebrew/lib/python3.14/site-packages/playwright/_impl/_sync_base.py", line 115, in _sync
return task.result()
~~~~~~~~~~~^^
File "/opt/homebrew/lib/python3.14/site-packages/playwright/_impl/_page.py", line 1110, in wait_for_function
return await self._main_frame.wait_for_function(**locals_to_params(locals()))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.14/site-packages/playwright/_impl/_frame.py", line 878, in wait_for_function
await self._channel.send("waitForFunction", self._timeout, params)
File "/opt/homebrew/lib/python3.14/site-packages/playwright/_impl/_connection.py", line 69, in send
return await self._connection.wrap_api_call(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<3 lines>...
)
^
File "/opt/homebrew/lib/python3.14/site-packages/playwright/_impl/_connection.py", line 559, in wrap_api_call
raise rewrite_error(error, f"{parsed_st['apiName']}: {error}") from None
playwright._impl._errors.Error: Page.wait_for_function: SyntaxError: missing ) after argument list
at eval (<anonymous>)
at predicate (eval at evaluate (:290:30), <anonymous>:4:56)
at next (eval at evaluate (:290:30), <anonymous>:29:29)
at eval (eval at evaluate (:290:30), <anonymous>:42:9)
at UtilityScript.evaluate (<anonymous>:292:16)
at UtilityScript.<anonymous> (<anonymous>:1:44)
@@ -0,0 +1,23 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs(86,9): error CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. [/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.csproj]
/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs(91,9): error CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. [/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.csproj]
/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs(92,9): error CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call. [/Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.csproj]
@@ -0,0 +1,34 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.34] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryDuringNextRead_WaitsWithoutOverlapAndCoalescesDuplicateTarget [FAIL]
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryDuringNextRead_WaitsWithoutOverlapAndCoalescesDuplicateTarget [197 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 1
Actual: 3
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryDuringNextRead_WaitsWithoutOverlapAndCoalescesDuplicateTarget() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 86
--- End of stack trace from previous location ---
Failed! - Failed: 1, Passed: 0, Skipped: 0, Total: 1, Duration: 204 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,25 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 30, Skipped: 0, Total: 30, Duration: 427 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 426 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 419 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 436 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,26 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Results File: /Users/dohertj2/Desktop/ScadaBridge/docs/ui-consistency/evidence/sb04-06/sb04-06.trx
Passed! - Failed: 0, Passed: 1575, Skipped: 0, Total: 1575, Duration: 34 s - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,25 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 6, Skipped: 0, Total: 6, Duration: 239 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 17, Skipped: 0, Total: 17, Duration: 394 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,25 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 21, Skipped: 0, Total: 21, Duration: 435 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 17, Skipped: 0, Total: 17, Duration: 411 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,25 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 31, Skipped: 0, Total: 31, Duration: 439 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,19 @@
{
"partialInput": {
"value": "",
"badInput": true,
"valid": false
},
"afterPartialApply": "No local filter applied",
"focusedInvalidInput": true,
"formCount": 1,
"chromiumAXInvalid": "true",
"explicitAriaInvalid": null,
"clearedInput": {
"value": "",
"badInput": false,
"valid": true
},
"afterIntentionalClear": "From=;To=;FromKind=;ToKind=",
"passed": true
}
@@ -0,0 +1,6 @@
{
"nativeBadInput": true,
"explicitAriaInvalid": "false",
"chromiumAXInvalid": "false",
"finding": "Explicit aria-invalid=false masked native badInput; form submission already blocked safely."
}
@@ -0,0 +1,8 @@
{
"beforeApply": {
"value": "",
"badInput": true,
"valid": false
},
"afterApply": "From=;To=;FromKind=;ToKind="
}
@@ -0,0 +1,537 @@
[
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Login.razor",
"routes": [
"/login"
],
"h1Count": 0,
"firstHeading": null,
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Dashboard.razor",
"routes": [
"/"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Welcome to ScadaBridge"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ApiMethodForm.razor",
"routes": [
"/design/api-methods/create",
"/design/api-methods/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? \"Edit API Method\" : \"Add API Method\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystemForm.razor",
"routes": [
"/design/external-systems/create",
"/design/external-systems/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? \"Edit External System\" : \"Add External System\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportImport.razor",
"routes": [
"/design/transport/import"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Import Bundle"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScripts.razor",
"routes": [
"/design/shared-scripts"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Shared Scripts"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateEdit.razor",
"routes": [
"/design/templates/{Id:int}"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@_selectedTemplate.Name"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ConnectionCertificates.razor",
"routes": [
"/design/connections/{Id:int}/certificates"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Server Certificates@(string.IsNullOrEmpty(_connectionName) ? \"\" : $\" \u2014 {_connectionName}\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnections.razor",
"routes": [
"/design/connections",
"/design/data-connections"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Connections"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DbConnectionForm.razor",
"routes": [
"/design/db-connections/create",
"/design/db-connections/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? \"Edit Database Connection\" : \"Add Database Connection\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/DataConnectionForm.razor",
"routes": [
"/design/connections/create",
"/design/connections/{Id:int}/edit",
"/design/data-connections/create",
"/design/data-connections/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? \"Edit Data Connection\" : \"Add Data Connection\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/Templates.razor",
"routes": [
"/design/templates"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Templates"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/ExternalSystems.razor",
"routes": [
"/design/external-systems"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Integration Definitions"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TemplateCreate.razor",
"routes": [
"/design/templates/create"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Create Template"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SchemaLibrary.razor",
"routes": [
"/design/schema-library"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Schema Library"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/SharedScriptForm.razor",
"routes": [
"/design/shared-scripts/create",
"/design/shared-scripts/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? $\"Edit Shared Script: {_formName}\" : \"New Shared Script\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Design/TransportExport.razor",
"routes": [
"/design/transport/export"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Export Bundle"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/Sites.razor",
"routes": [
"/admin/sites"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Site Management"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeyForm.razor",
"routes": [
"/admin/api-keys/create",
"/admin/api-keys/{KeyId}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@if (_saved)\n {\n @:API Key Created\n }\n else if (IsEd"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/LdapMappings.razor",
"routes": [
"/admin/ldap-mappings"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "LDAP Group Mappings"
},
"tableDarkCount": 1
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/LdapMappingForm.razor",
"routes": [
"/admin/ldap-mappings/create",
"/admin/ldap-mappings/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "5",
"text": "Mapping"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/SiteForm.razor",
"routes": [
"/admin/sites/create",
"/admin/sites/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": null,
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/ApiKeys.razor",
"routes": [
"/admin/api-keys"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "API Key Management"
},
"tableDarkCount": 1
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Operations/SecuredWrites.razor",
"routes": [
"/operations/secured-writes"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Secured Writes"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor",
"routes": [
"/audit/configuration"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Configuration Audit Log"
},
"tableDarkCount": 1
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ExecutionTreePage.razor",
"routes": [
"/audit/execution-tree"
],
"h1Count": 1,
"firstHeading": {
"level": "1",
"text": "Execution Chain"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor",
"routes": [
"/audit/log"
],
"h1Count": 1,
"firstHeading": {
"level": "1",
"text": "Audit Log"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor",
"routes": [
"/deployment/topology",
"/deployment/instances"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Topology"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Deployments.razor",
"routes": [
"/deployment/deployments"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Deployment Status"
},
"tableDarkCount": 1
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceCreate.razor",
"routes": [
"/deployment/instances/create"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Create Instance"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/InstanceConfigure.razor",
"routes": [
"/deployment/instances/{Id:int}/configure"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Configure Instance"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/FlowDebugger.razor",
"routes": [
"/deployment/flow-debugger"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Flow Debugger"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/DebugView.razor",
"routes": [
"/deployment/debug-view"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Debug View"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/ParkedMessages.razor",
"routes": [
"/monitoring/parked-messages"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Parked Messages"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/AlarmSummary.razor",
"routes": [
"/monitoring/alarms"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Alarm Summary"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor",
"routes": [
"/monitoring/health"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Health Dashboard"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/EventLogs.razor",
"routes": [
"/monitoring/event-logs"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Site Event Logs"
},
"tableDarkCount": 1
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor",
"routes": [
"/site-calls/report"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Site Calls"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/SmsConfiguration.razor",
"routes": [
"/notifications/sms"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "SMS Configuration"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/SmtpConfiguration.razor",
"routes": [
"/notifications/smtp"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "SMTP Configuration"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor",
"routes": [
"/notifications/kpis"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Notification KPIs"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationLists.razor",
"routes": [
"/notifications/lists"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Notification Lists"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationListForm.razor",
"routes": [
"/notifications/lists/create",
"/notifications/lists/{Id:int}/edit"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "@(Id.HasValue ? \"Edit Notification List\" : \"Add Notification List\")"
},
"tableDarkCount": 0
},
{
"file": "src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor",
"routes": [
"/notifications/report"
],
"h1Count": 0,
"firstHeading": {
"level": "4",
"text": "Notification Report"
},
"tableDarkCount": 0
}
]
@@ -0,0 +1,25 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 31, Skipped: 0, Total: 31, Duration: 431 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,84 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.36] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.DelayedRead_RemainsLoadingUntilKnownZeroArrives [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Sites configured") [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "API keys") [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Data connections configured") [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Templates") [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryFailure_PreservesSuccessfulFactsAndCanRecoverToZero [FAIL]
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.DelayedRead_RemainsLoadingUntilKnownZeroArrives [193 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[aria-label='API keys']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.DelayedRead_RemainsLoadingUntilKnownZeroArrives() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 70
--- End of stack trace from previous location ---
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Sites configured") [4 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[role=region][aria-label='Sites configured']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(String label) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 45
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "API keys") [1 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[role=region][aria-label='Sites configured']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(String label) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 45
at InvokeStub_DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Data connections configured") [1 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[role=region][aria-label='Sites configured']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(String label) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 45
at InvokeStub_DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(label: "Templates") [1 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[role=region][aria-label='Sites configured']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(String label) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 45
at InvokeStub_DashboardStateTests.CountFailure_DoesNotEraseOtherFactsOrRenderZero(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryFailure_PreservesSuccessfulFactsAndCanRecoverToZero [1 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector '[aria-label='API keys']'
Stack Trace:
at Bunit.RenderedComponentExtensions.Find[TComponent,TElement](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 42
at Bunit.RenderedComponentExtensions.Find[TComponent](IRenderedComponent`1 renderedComponent, String cssSelector) in /_/src/bunit/Extensions/RenderedComponentExtensions.cs:line 21
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages.DashboardStateTests.RetryFailure_PreservesSuccessfulFactsAndCanRecoverToZero() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs:line 56
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Failed! - Failed: 6, Passed: 0, Skipped: 0, Total: 6, Duration: 213 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,84 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.31] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.ToastNotificationTests.ToastDismiss_HasContextualNameAndPreservesOtherNotification [FAIL]
[xUnit.net 00:00:00.33] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-11-01T01:30", to: "2026-11-01T02:30") [FAIL]
[xUnit.net 00:00:00.35] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-03-08T01:30", to: "2026-03-08T02:30") [FAIL]
[xUnit.net 00:00:00.36] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-11-12T10:00", to: "2026-11-12T11:00") [FAIL]
[xUnit.net 00:00:00.37] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(from: "not-a-date", to: "2026-11-12T11:00") [FAIL]
[xUnit.net 00:00:00.39] ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(from: "2026-11-12T12:00", to: "2026-11-12T11:00") [FAIL]
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.ToastNotificationTests.ToastDismiss_HasContextualNameAndPreservesOtherNotification [154 ms]
Error Message:
Assert.Equal() Failure: Strings differ
Expected: "Dismiss Configuration"
Actual: null
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared.ToastNotificationTests.ToastDismiss_HasContextualNameAndPreservesOtherNotification() in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/ToastNotificationTests.cs:line 25
--- End of stack trace from previous location ---
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-11-01T01:30", to: "2026-11-01T02:30") [182 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 2026-11-01T01:30:00.0000000Z
Actual: 2026-11-01T06:30:00.0000000Z
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(String from, String to) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs:line 73
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-03-08T01:30", to: "2026-03-08T02:30") [20 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 2026-03-08T01:30:00.0000000Z
Actual: 2026-03-08T06:30:00.0000000Z
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(String from, String to) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs:line 73
at InvokeStub_AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(from: "2026-11-12T10:00", to: "2026-11-12T11:00") [11 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 2026-11-12T10:00:00.0000000Z
Actual: 2026-11-12T15:00:00.0000000Z
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(String from, String to) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs:line 73
at InvokeStub_AuditFilterBarTests.CustomUtcWindow_PreservesLiteralInstantsAndInputText(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(from: "not-a-date", to: "2026-11-12T11:00") [14 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 0
Actual: 1
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(String from, String to) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs:line 90
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
Failed ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(from: "2026-11-12T12:00", to: "2026-11-12T11:00") [11 ms]
Error Message:
Assert.Equal() Failure: Values differ
Expected: 0
Actual: 1
Stack Trace:
at ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Audit.AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(String from, String to) in /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs:line 90
at InvokeStub_AuditFilterBarTests.InvalidCustomWindow_DoesNotQueryUntilCorrected(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
Failed! - Failed: 6, Passed: 0, Skipped: 0, Total: 6, Duration: 240 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,26 @@
ZB.MOM.WW.ScadaBridge.Commons -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Commons/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Commons.dll
ZB.MOM.WW.ScadaBridge.KpiHistory -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.KpiHistory/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.KpiHistory.dll
ZB.MOM.WW.ScadaBridge.ConfigurationDatabase -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.dll
ZB.MOM.WW.ScadaBridge.Communication -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Communication.dll
ZB.MOM.WW.ScadaBridge.Security -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Security/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Security.dll
ZB.MOM.WW.ScadaBridge.ScriptAnalysis -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ScriptAnalysis/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ScriptAnalysis.dll
ZB.MOM.WW.ScadaBridge.SiteEventLogging -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.SiteEventLogging.dll
ZB.MOM.WW.ScadaBridge.StoreAndForward -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.StoreAndForward/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.StoreAndForward.dll
ZB.MOM.WW.ScadaBridge.TemplateEngine -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.TemplateEngine.dll
ZB.MOM.WW.ScadaBridge.AuditLog -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.AuditLog/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.AuditLog.dll
ZB.MOM.WW.ScadaBridge.Transport -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Transport/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.Transport.dll
ZB.MOM.WW.ScadaBridge.DeploymentManager -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.DeploymentManager/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.DeploymentManager.dll
ZB.MOM.WW.ScadaBridge.NotificationService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationService.dll
ZB.MOM.WW.ScadaBridge.HealthMonitoring -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.HealthMonitoring/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.HealthMonitoring.dll
ZB.MOM.WW.ScadaBridge.ExternalSystemGateway -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.dll
ZB.MOM.WW.ScadaBridge.InboundAPI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.InboundAPI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.InboundAPI.dll
ZB.MOM.WW.ScadaBridge.NotificationOutbox -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.NotificationOutbox.dll
ZB.MOM.WW.ScadaBridge.ManagementService -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.ManagementService/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.ManagementService.dll
ZB.MOM.WW.ScadaBridge.CentralUI -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.dll
ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker -> /Users/dohertj2/Desktop/ScadaBridge/src/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.SandboxWorker.dll
ZB.MOM.WW.ScadaBridge.CentralUI.Tests -> /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Results File: /Users/dohertj2/Desktop/ScadaBridge/docs/ui-consistency/evidence/sb04-06/sb04-06-reviewed.trx
Passed! - Failed: 0, Passed: 1576, Skipped: 0, Total: 1576, Duration: 33 s - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 385 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 387 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
@@ -0,0 +1,4 @@
Test run for /Users/dohertj2/Desktop/ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/bin/Release/net10.0/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (.NETCoreApp,Version=v10.0)
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 20, Skipped: 0, Total: 20, Duration: 388 ms - ZB.MOM.WW.ScadaBridge.CentralUI.Tests.dll (net10.0)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
{
"src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor": "f7be9e2db5dc5d9918407fd44d882607f6fd5f0206f1d77ea2ca228cfb3f5465",
"src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor.cs": "c9e2de1c30deefb7c50d004d3eed79af5ea884756bffd994a76448354eb9b437",
"src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Dashboard.razor": "05451dfe2553780f57ca6a48a82b62b705eb1ac886529a88e5d4027810e49c78",
"src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/ToastNotification.razor": "46a697b0ace8f8e0ae56cbc56e0d163f33b208997561507fa8e94effde730cce",
"tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/Audit/AuditFilterBarTests.cs": "a864db3e2684206484b9899c424f5180a702c9ab79425526aec98c69709cbf8c",
"tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Shared/ToastNotificationTests.cs": "f5919368f774dea91fcd6ac68c8b5d08aef5574b3dd7e4c513abadc3bdf94237",
"tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/DashboardStateTests.cs": "caae26824167e982df67ad54ba248564f4fb1e05e7b801869e8106f6eb1029b2",
"infra/tools/inspect_states_and_utc.py": "2bee439711c17b9b21ed371bc4710ba1c2397f64d2ade0964a15293a5a6ec90d",
"infra/tools/test_native_utc_constraint.py": "bdfb23fd0ece50ec1327fe31c0a56725acef3a55d9ef50a898f4ec46769b8345"
}
+20
View File
@@ -0,0 +1,20 @@
"""Bounded local actual-component state/UTC check; never submits a backend write."""
from pathlib import Path
import json
from playwright.sync_api import sync_playwright
out=Path('docs/ui-consistency/evidence/sb04-06/browser-confirmation');out.mkdir(parents=True,exist_ok=True);results=[]
with sync_playwright() as p:
browser=p.chromium.launch(channel='chromium')
for width in [1440,390]:
for zone in ['America/New_York','Asia/Tokyo']:
page=browser.new_page(viewport={'width':width,'height':1000},timezone_id=zone,reduced_motion='reduce');page.goto('http://127.0.0.1:5201/batch-two?sample=audit',wait_until='networkidle');page.select_option('#audit-time-range','Custom');page.fill('#audit-from','2026-03-08T01:30');page.fill('#audit-to','2026-03-08T02:30');page.click('[data-test=filter-apply]');page.wait_for_function('document.querySelector("#local-filter-result").textContent.includes("FromKind=Utc")');text=page.locator('#local-filter-result').inner_text();record={'sample':'audit','width':width,'browserZone':zone,'utcResult':text,'checks':{'literalUTC':'From=2026-03-08T01:30:00.0000000Z' in text and 'To=2026-03-08T02:30:00.0000000Z' in text}}
page.fill('#audit-from','2026-03-08T03:30');page.click('[data-test=filter-apply]');page.locator('#audit-range-error').wait_for();record['checks']['invertedBlocked']=page.locator('#local-filter-result').inner_text()==text and page.get_attribute('#audit-from','aria-invalid')=='true';record['errorColor']=page.locator('#audit-range-error').evaluate('e=>getComputedStyle(e).color');record['checks']['correctionPreserved']=page.input_value('#audit-from')=='2026-03-08T03:30';page.screenshot(path=str(out/f'audit-{zone.split("/")[-1]}-{width}.png'),full_page=True);results.append(record);page.close()
for sample in ['dashboard','toast']:
page=browser.new_page(viewport={'width':width,'height':1000},reduced_motion='reduce');page.goto('http://127.0.0.1:5201/batch-two?sample='+sample,wait_until='networkidle');record={'sample':sample,'width':width,'checks':{}}
if sample=='dashboard':
fact=page.locator('[role=region][aria-label="API keys"]');record['checks']['unavailableNotZero']='Unavailable' in fact.inner_text();page.get_by_role('button',name='Retry API keys',exact=True).click();page.wait_for_function('selector=>{const text=document.querySelector(selector).textContent;return !text.includes("Unavailable")&&!text.includes("Loading");}',arg='[role=region][aria-label="API keys"]');record['checks']['retryKnownZero']='0' in fact.inner_text() and 'Unavailable' not in fact.inner_text();record['checks']['otherFactsRemain']=all('0' in page.locator('[role=region][aria-label="'+label+'"]').inner_text() for label in ['Sites configured','Data connections configured','Templates'])
else:
page.click('#show-toast');page.get_by_role('button',name='Dismiss Local configuration',exact=True).click();page.wait_for_function('document.querySelectorAll(".toast").length===1');record['checks']['onlyTargetDismissed']=page.locator('.toast').count()==1 and 'Local audit query' in page.locator('.toast').inner_text();record['checks']['otherDismissNamed']=page.get_by_role('button',name='Dismiss Local audit query',exact=True).count()==1
record['layout']=page.evaluate('({innerWidth,scrollWidth:document.documentElement.scrollWidth})');page.screenshot(path=str(out/f'{sample}-{width}.png'),full_page=True);results.append(record);page.close()
browser.close()
(out/'results.json').write_text(json.dumps({'results':results,'passed':all(all(r['checks'].values()) for r in results)},indent=2)+'\n');print([(r['sample'],r['width'],all(r['checks'].values())) for r in results])
@@ -0,0 +1,6 @@
"""Actual keyboard partial date validation; no synthetic .value='invalid' workaround."""
from pathlib import Path
import json
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
b=p.chromium.launch(channel='chromium');page=b.new_page(locale='en-US');page.goto('http://127.0.0.1:5201/batch-two?sample=audit',wait_until='networkidle');page.select_option('#audit-time-range','Custom');page.locator('#audit-from').focus();page.keyboard.press('ArrowLeft');page.keyboard.type('1');page.keyboard.press('Tab');before=page.locator('#audit-from').evaluate('e=>({value:e.value,badInput:e.validity.badInput,valid:e.validity.valid})');page.click('[data-test=filter-apply]');page.wait_for_timeout(100);record={'partialInput':before,'afterPartialApply':page.locator('#local-filter-result').inner_text(),'focusedInvalidInput':page.locator('#audit-from').evaluate('e=>e===document.activeElement'),'formCount':page.locator('form[data-test=audit-filter-bar]').count()};cdp=page.context.new_cdp_session(page);doc=cdp.send('DOM.getDocument');node=cdp.send('DOM.querySelector',{'nodeId':doc['root']['nodeId'],'selector':'#audit-from'});ax=cdp.send('Accessibility.getPartialAXTree',{'nodeId':node['nodeId'],'fetchRelatives':False});record['chromiumAXInvalid']=next((x['value']['value'] for x in ax['nodes'][0].get('properties',[]) if x['name']=='invalid'),None);record['explicitAriaInvalid']=page.get_attribute('#audit-from','aria-invalid');page.fill('#audit-from','');page.locator('#audit-to').focus();record['clearedInput']=page.locator('#audit-from').evaluate('e=>({value:e.value,badInput:e.validity.badInput,valid:e.validity.valid})');page.click('[data-test=filter-apply]');page.wait_for_function('document.querySelector("#local-filter-result").textContent.startsWith("From=")');record['afterIntentionalClear']=page.locator('#local-filter-result').inner_text();record['passed']=before['badInput'] and record['afterPartialApply']=='No local filter applied' and record['focusedInvalidInput'] and record['chromiumAXInvalid']=='true' and record['clearedInput']['valid'] and record['afterIntentionalClear']=='From=;To=;FromKind=;ToKind=';Path('docs/ui-consistency/evidence/sb04-06/native-partial-after.json').write_text(json.dumps(record,indent=2)+'\n');print(record);b.close()
@@ -6,7 +6,7 @@
@inject ISiteRepository SiteRepository
@inject IAuditLogQueryService AuditLogQueryService
<div class="card mb-3" data-test="audit-filter-bar">
<form class="card mb-3" data-test="audit-filter-bar" aria-label="Audit filters" @onsubmit="Apply" @onsubmit:preventDefault>
<div class="card-body py-2">
@* All filters sit in one wrapped row. Kind / Status / Site use compact
MultiSelectDropdown controls; Channel is a single-select because the
@@ -91,17 +91,27 @@
<div class="col-auto" data-test="filter-custom-range">
@if (_model.TimeRange == AuditTimeRangePreset.Custom)
{
@* DateTimeRangeFilter is INPUT-ONLY: it surfaces the raw datetime-local
picks (DateTimeKind.Unspecified) straight into the model's range fields.
The local→UTC conversion still happens later in Apply()/LocalInputToUtc,
exactly as before. IdPrefix="audit" keeps the audit-from/audit-to ids. *@
<DateTimeRangeFilter From="_model.CustomFromUtc"
FromChanged="@(v => _model.CustomFromUtc = v)"
To="_model.CustomToUtc"
ToChanged="@(v => _model.CustomToUtc = v)"
IdPrefix="audit"
FromLabel="From (UTC)"
ToLabel="To (UTC)" />
<div class="row g-2 align-items-end">
<div class="col-auto">
<label class="form-label small mb-1" for="audit-from">From (UTC)</label>
<input id="audit-from" data-test="audit-from" type="datetime-local" step="any" class="form-control form-control-sm"
value="@_customFromText" @onchange="e => _customFromText = e.Value?.ToString() ?? string.Empty"
aria-invalid="@(_customRangeError is not null ? "true" : null)"
aria-describedby="@(_customRangeError is not null ? "audit-range-error" : "audit-utc-hint")" />
</div>
<div class="col-auto">
<label class="form-label small mb-1" for="audit-to">To (UTC)</label>
<input id="audit-to" data-test="audit-to" type="datetime-local" step="any" class="form-control form-control-sm"
value="@_customToText" @onchange="e => _customToText = e.Value?.ToString() ?? string.Empty"
aria-invalid="@(_customRangeError is not null ? "true" : null)"
aria-describedby="@(_customRangeError is not null ? "audit-range-error" : "audit-utc-hint")" />
</div>
</div>
<div id="audit-utc-hint" class="form-text">Enter UTC values. Leave either bound empty for an open-ended range.</div>
@if (_customRangeError is not null)
{
<div id="audit-range-error" class="field-error s-bad small" role="alert">@_customRangeError</div>
}
}
else
{
@@ -163,12 +173,11 @@
<div class="col-auto ms-auto">
<div class="btn-group btn-group-sm" role="group">
<button class="btn btn-outline-secondary"
<button type="button" class="btn btn-outline-secondary"
@onclick="ClearFilters" data-test="filter-clear">Clear</button>
<button class="btn btn-primary"
@onclick="Apply" data-test="filter-apply">Apply</button>
<button type="submit" class="btn btn-primary" data-test="filter-apply">Apply</button>
</div>
</div>
</div>
</div>
</div>
</form>
@@ -20,6 +20,9 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Audit;
public partial class AuditFilterBar
{
private readonly AuditQueryModel _model = new();
private string _customFromText = string.Empty;
private string _customToText = string.Empty;
private string? _customRangeError;
private List<Site> _sites = new();
/// <summary>Channel options — the full enum, fixed for the component's lifetime.</summary>
@@ -154,6 +157,8 @@ public partial class AuditFilterBar
_model.SiteIdentifiers.Clear();
_model.SourceNodes.Clear();
_model.TimeRange = AuditTimeRangePreset.LastHour;
_customFromText = _customToText = string.Empty;
_customRangeError = null;
_model.CustomFromUtc = null;
_model.CustomToUtc = null;
_model.InstanceSearch = string.Empty;
@@ -167,38 +172,35 @@ public partial class AuditFilterBar
private async Task Apply()
{
// <input type="datetime-local"> binds with DateTimeKind.Unspecified
// — the value is the user's browser-local wall-clock. Tag it as Local then convert
// to UTC before the model emits the filter, otherwise a non-UTC operator's window
// is silently shifted by their UTC offset. Done on a swap-and-restore basis so the
// bound inputs still show the user's local picks on the next render.
var originalFrom = _model.CustomFromUtc;
var originalTo = _model.CustomToUtc;
try
_customRangeError = null;
if (_model.TimeRange == AuditTimeRangePreset.Custom)
{
_model.CustomFromUtc = LocalInputToUtc(originalFrom);
_model.CustomToUtc = LocalInputToUtc(originalTo);
var now = NowUtcProvider?.Invoke() ?? DateTime.UtcNow;
var filter = _model.ToFilter(now);
await OnFilterChanged.InvokeAsync(filter);
}
finally
{
_model.CustomFromUtc = originalFrom;
_model.CustomToUtc = originalTo;
if (!TryUtcInput(_customFromText, out var from) || !TryUtcInput(_customToText, out var to))
{
_customRangeError = "Enter valid UTC date and time values, or clear an optional bound.";
return;
}
if (from.HasValue && to.HasValue && from > to)
{
_customRangeError = "From (UTC) must be before or equal to To (UTC). Correct the range before applying.";
return;
}
_model.CustomFromUtc = from;
_model.CustomToUtc = to;
}
var now = NowUtcProvider?.Invoke() ?? DateTime.UtcNow;
await OnFilterChanged.InvokeAsync(_model.ToFilter(now));
}
/// <summary>
/// Converts a value bound from <c>&lt;input type="datetime-local"&gt;</c> (which Blazor
/// surfaces as <see cref="DateTimeKind.Unspecified"/>) into UTC. The input represents
/// the operator's browser-local wall-clock, so we must tag it <see cref="DateTimeKind.Local"/>
/// before <see cref="DateTime.ToUniversalTime"/> can do anything meaningful.
/// </summary>
private static DateTime? LocalInputToUtc(DateTime? value) =>
value.HasValue
? DateTime.SpecifyKind(value.Value, DateTimeKind.Local).ToUniversalTime()
: (DateTime?)null;
private static bool TryUtcInput(string raw, out DateTime? value)
{
value = null;
if (string.IsNullOrWhiteSpace(raw)) return true;
if (!DateTime.TryParseExact(raw, ["yyyy-MM-dd'T'HH:mm", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.FFFFFFF"],
System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var parsed)) return false;
value = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
return true;
}
private static string TimeRangeLabel(AuditTimeRangePreset preset) => preset switch
{
@@ -22,33 +22,49 @@
@* KPI row *@
<div class="row g-3 mb-4">
<div class="col-lg-3 col-md-6 col-12">
<div class="card h-100">
<div class="card h-100" role="region" aria-label="Sites configured">
<div class="card-body text-center">
<div class="fs-2 fw-bold">@(_loaded ? _siteCount.ToString() : "—")</div>
<div class="fs-2 fw-bold" role="status" aria-live="polite">@CountText(_sites)</div>
@if (_sites.Failed)
{
<button type="button" class="btn btn-sm btn-outline-secondary" disabled="@_sites.Loading" @onclick="LoadSites">Retry Sites configured</button>
}
<div class="text-muted small">Sites configured</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-12">
<div class="card h-100">
<div class="card h-100" role="region" aria-label="Data connections configured">
<div class="card-body text-center">
<div class="fs-2 fw-bold">@(_loaded ? _dataConnectionCount.ToString() : "—")</div>
<div class="fs-2 fw-bold" role="status" aria-live="polite">@CountText(_connections)</div>
@if (_connections.Failed)
{
<button type="button" class="btn btn-sm btn-outline-secondary" disabled="@_connections.Loading" @onclick="LoadConnections">Retry Data connections configured</button>
}
<div class="text-muted small">Data connections configured</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-12">
<div class="card h-100">
<div class="card h-100" role="region" aria-label="Templates">
<div class="card-body text-center">
<div class="fs-2 fw-bold">@(_loaded ? _templateCount.ToString() : "—")</div>
<div class="fs-2 fw-bold" role="status" aria-live="polite">@CountText(_templates)</div>
@if (_templates.Failed)
{
<button type="button" class="btn btn-sm btn-outline-secondary" disabled="@_templates.Loading" @onclick="LoadTemplates">Retry Templates</button>
}
<div class="text-muted small">Templates</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 col-12">
<div class="card h-100">
<div class="card h-100" role="region" aria-label="API keys">
<div class="card-body text-center">
<div class="fs-2 fw-bold">@(_loaded ? _apiKeyCount.ToString() : "—")</div>
<div class="fs-2 fw-bold" role="status" aria-live="polite">@CountText(_apiKeys)</div>
@if (_apiKeys.Failed)
{
<button type="button" class="btn btn-sm btn-outline-secondary" disabled="@_apiKeys.Loading" @onclick="LoadApiKeys">Retry API keys</button>
}
<div class="text-muted small">API keys</div>
</div>
</div>
@@ -95,25 +111,58 @@
</div>
@code {
private bool _loaded;
private int _siteCount;
private int _dataConnectionCount;
private int _templateCount;
private int _apiKeyCount;
private Task _countReadTail = Task.CompletedTask;
private readonly CountState _sites = new();
private readonly CountState _connections = new();
private readonly CountState _templates = new();
private readonly CountState _apiKeys = new();
private sealed class CountState
{
public int? Value { get; set; }
public bool Loading { get; set; } = true;
public bool Failed { get; set; }
public bool Pending { get; set; }
}
private static string CountText(CountState state) => state.Failed ? "Unavailable" : state.Loading ? "Loading…" : state.Value?.ToString() ?? "Unavailable";
protected override async Task OnInitializedAsync()
{
// Keep repository calls sequential: some implementations share a scoped
// DbContext. Each fact still settles independently, including failures.
await LoadSites();
await LoadConnections();
await LoadTemplates();
await LoadApiKeys();
}
private Task LoadSites() => LoadCount(_sites, async () => (await SiteRepository.GetAllSitesAsync()).Count);
private Task LoadConnections() => LoadCount(_connections, async () => (await SiteRepository.GetAllDataConnectionsAsync()).Count);
private Task LoadTemplates() => LoadCount(_templates, async () => (await TemplateEngineRepository.GetTemplateStubsAsync()).Count);
private Task LoadApiKeys() => LoadCount(_apiKeys, async () => (await ApiKeyAdmin.ListAsync()).Count);
private async Task LoadCount(CountState state, Func<Task<int>> read)
{
// Renderer callbacks enter serially. Claim this fact before the first
// await, then queue every initial/retry read behind the same component gate.
if (state.Pending) return;
state.Pending = true;
state.Loading = true;
state.Failed = false;
var previous = _countReadTail;
var released = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
_countReadTail = released.Task;
try
{
_siteCount = (await SiteRepository.GetAllSitesAsync()).Count;
_dataConnectionCount = (await SiteRepository.GetAllDataConnectionsAsync()).Count;
_templateCount = (await TemplateEngineRepository.GetTemplateStubsAsync()).Count;
_apiKeyCount = (await ApiKeyAdmin.ListAsync()).Count;
await previous;
state.Value = await read();
}
catch
catch { state.Failed = true; }
finally
{
// Non-fatal — leave counts at zero with the placeholder rendering.
state.Loading = false;
state.Pending = false;
released.TrySetResult();
StateHasChanged();
}
_loaded = true;
}
}
@@ -17,7 +17,7 @@
<div class="toast show mb-2" role="alert">
<div class="toast-header @GetHeaderClass(toast.Type)">
<strong class="me-auto">@toast.Title</strong>
<button type="button" class="btn-close btn-close-white" @onclick="() => Dismiss(toast)"></button>
<button type="button" aria-label="@($"Dismiss {toast.Title}")" class="btn-close btn-close-white" @onclick="() => Dismiss(toast)"></button>
</div>
<div class="toast-body">@toast.Message</div>
</div>
@@ -57,6 +57,63 @@ public class AuditFilterBarTests : BunitContext
Services.AddSingleton(_auditLogQueryService);
}
/// <summary>UTC-labelled custom picks are identical in every process timezone.</summary>
[Theory]
[InlineData("2026-11-12T10:00", "2026-11-12T11:00")]
[InlineData("2026-03-08T01:30", "2026-03-08T02:30")]
[InlineData("2026-11-01T01:30", "2026-11-01T02:30")]
public void CustomUtcWindow_PreservesLiteralInstantsAndInputText(string from, string to)
{
AuditLogQueryFilter? captured = null;
var cut = Render<AuditFilterBar>(p => p.Add(c => c.OnFilterChanged, f => captured = f));
cut.Find("#audit-time-range").Change(AuditTimeRangePreset.Custom.ToString());
cut.Find("#audit-from").Change(from); cut.Find("#audit-to").Change(to);
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(DateTime.SpecifyKind(DateTime.Parse(from, System.Globalization.CultureInfo.InvariantCulture), DateTimeKind.Utc), captured.FromUtc);
Assert.Equal(DateTime.SpecifyKind(DateTime.Parse(to, System.Globalization.CultureInfo.InvariantCulture), DateTimeKind.Utc), captured.ToUtc);
Assert.Equal(from, cut.Find("#audit-from").GetAttribute("value"));
Assert.Equal(to, cut.Find("#audit-to").GetAttribute("value"));
}
/// <summary>Intentional nullable bounds retain the existing open-ended query contract.</summary>
[Theory]
[InlineData("", "2026-11-12T11:00")]
[InlineData("2026-11-12T10:00", "")]
[InlineData("", "")]
public void CustomUtcWindow_EmptyBoundsRemainIntentional(string from, string to)
{
AuditLogQueryFilter? captured = null;
var cut = Render<AuditFilterBar>(p => p.Add(c => c.OnFilterChanged, f => captured = f));
cut.Find("#audit-time-range").Change(AuditTimeRangePreset.Custom.ToString());
cut.Find("#audit-from").Change(from); cut.Find("#audit-to").Change(to);
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(string.IsNullOrEmpty(from), captured.FromUtc is null);
Assert.Equal(string.IsNullOrEmpty(to), captured.ToUtc is null);
}
/// <summary>Bad ranges retain correction text without emitting a broader query.</summary>
[Theory]
[InlineData("not-a-date", "2026-11-12T11:00")]
[InlineData("2026-11-12T12:00", "2026-11-12T11:00")]
public void InvalidCustomWindow_DoesNotQueryUntilCorrected(string from, string to)
{
var queries = 0;
var cut = Render<AuditFilterBar>(p => p.Add(c => c.OnFilterChanged, _ => queries++));
cut.Find("#audit-time-range").Change(AuditTimeRangePreset.Custom.ToString());
cut.Find("#audit-from").Change(from); cut.Find("#audit-to").Change(to);
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Equal(0, queries);
Assert.Equal(from, cut.Find("#audit-from").GetAttribute("value"));
Assert.Equal("true", cut.Find("#audit-from").GetAttribute("aria-invalid"));
Assert.NotEmpty(cut.Find("#" + cut.Find("#audit-from").GetAttribute("aria-describedby")).TextContent);
cut.Find("#audit-from").Change("2026-11-12T10:00");
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Equal(1, queries);
Assert.Null(cut.Find("#audit-from").GetAttribute("aria-invalid"));
}
/// <summary>Verifies that the filter bar renders all ten filter elements plus the errors-only toggle.</summary>
[Fact]
public void Render_AllTenElements_Plus_ErrorsOnlyToggle_Present()
@@ -99,7 +156,7 @@ public class AuditFilterBarTests : BunitContext
// Drive UI: pick a Channel, type in the Target search box, click Apply.
cut.Find("[data-test=\"filter-channel-select\"]").Change("ApiOutbound");
cut.Find("[data-test=\"filter-target\"] input").Change("Plant-A-OPC");
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(new[] { AuditChannel.ApiOutbound }, captured!.Channels);
@@ -118,14 +175,14 @@ public class AuditFilterBarTests : BunitContext
cut.Find("[data-test=\"filter-channel-select\"]").Change("ApiOutbound");
cut.Find("[data-test=\"filter-channel-select\"]").Change("Notification");
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(new[] { AuditChannel.Notification }, captured!.Channels);
// Selecting "All channels" clears the channel filter entirely.
cut.Find("[data-test=\"filter-channel-select\"]").Change(string.Empty);
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Null(captured!.Channels);
}
@@ -164,7 +221,7 @@ public class AuditFilterBarTests : BunitContext
// Toggle Errors-only ON, leaving Status chips empty.
cut.Find("[data-test=\"filter-errors-only\"] input").Change(true);
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
// Errors-only targets the full non-success set {Failed, Parked, Discarded}.
@@ -176,7 +233,7 @@ public class AuditFilterBarTests : BunitContext
// Now pin an explicit Status option — Errors-only must yield (explicit wins).
cut.Find("[data-test=\"filter-status-ms-opt-Delivered\"]").Change(true);
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Equal(new[] { AuditStatus.Delivered }, captured!.Statuses);
}
@@ -199,7 +256,7 @@ public class AuditFilterBarTests : BunitContext
Assert.Contains("data-test=\"filter-node-ms-opt-central-b\"", cut.Markup);
cut.Find("[data-test=\"filter-node-ms-opt-central-a\"]").Change(true);
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.NotNull(captured!.SourceNodes);
@@ -218,7 +275,7 @@ public class AuditFilterBarTests : BunitContext
cut.Find("[data-test=\"filter-status-ms-opt-Delivered\"]").Change(true);
cut.Find("[data-test=\"filter-status-ms-opt-Failed\"]").Change(true);
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.NotNull(captured!.Statuses);
@@ -239,7 +296,7 @@ public class AuditFilterBarTests : BunitContext
.Add(c => c.OnFilterChanged, EventCallback.Factory.Create<AuditLogQueryFilter>(this, f => captured = f)));
cut.Find("[data-test=\"filter-execution-id\"] input").Change(executionId.ToString());
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(executionId, captured!.ExecutionId);
@@ -255,13 +312,13 @@ public class AuditFilterBarTests : BunitContext
.Add(c => c.OnFilterChanged, EventCallback.Factory.Create<AuditLogQueryFilter>(this, f => captured = f)));
// Blank — never typed into.
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Null(captured!.ExecutionId);
// Unparseable paste — still dropped, no error.
cut.Find("[data-test=\"filter-execution-id\"] input").Change("not-a-guid");
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Null(captured!.ExecutionId);
}
@@ -277,7 +334,7 @@ public class AuditFilterBarTests : BunitContext
.Add(c => c.OnFilterChanged, EventCallback.Factory.Create<AuditLogQueryFilter>(this, f => captured = f)));
cut.Find("[data-test=\"filter-parent-execution-id\"] input").Change(parentExecutionId.ToString());
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Equal(parentExecutionId, captured!.ParentExecutionId);
@@ -293,13 +350,13 @@ public class AuditFilterBarTests : BunitContext
.Add(c => c.OnFilterChanged, EventCallback.Factory.Create<AuditLogQueryFilter>(this, f => captured = f)));
// Blank — never typed into.
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.NotNull(captured);
Assert.Null(captured!.ParentExecutionId);
// Unparseable paste — still dropped, no error.
cut.Find("[data-test=\"filter-parent-execution-id\"] input").Change("not-a-guid");
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
Assert.Null(captured!.ParentExecutionId);
}
@@ -313,7 +370,7 @@ public class AuditFilterBarTests : BunitContext
// LastHour is the default preset; clicking Apply must collapse it to FromUtc.
var before = DateTime.UtcNow;
cut.Find("[data-test=\"filter-apply\"]").Click();
cut.Find("form[data-test=audit-filter-bar]").Submit();
var after = DateTime.UtcNow;
Assert.NotNull(captured);
@@ -0,0 +1,108 @@
using Bunit;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Security;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Templates;
using DashboardPage = ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Dashboard;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Pages;
/// <summary>Dashboard facts distinguish independent failures, loading and known zero.</summary>
public class DashboardStateTests : BunitContext
{
private readonly ISiteRepository _sites = Substitute.For<ISiteRepository>();
private readonly ITemplateEngineRepository _templates = Substitute.For<ITemplateEngineRepository>();
private readonly IInboundApiKeyAdmin _keys = Substitute.For<IInboundApiKeyAdmin>();
/// <summary>Registers deterministic read-only dependencies and a signed-in fixture.</summary>
public DashboardStateTests()
{
this.AddAuthorization().SetAuthorized("fixture");
_sites.GetAllSitesAsync().Returns(Task.FromResult<IReadOnlyList<Site>>([new("A", "a"), new("B", "b")]));
_sites.GetAllDataConnectionsAsync().Returns(Task.FromResult<IReadOnlyList<DataConnection>>([new("Link", "OpcUa", 1)]));
_templates.GetTemplateStubsAsync().Returns(Task.FromResult<IReadOnlyList<TemplateStub>>([
new(1,"A",null,null,false,null), new(2,"B",null,null,false,null), new(3,"C",null,null,false,null)]));
_keys.ListAsync().Returns(Task.FromResult<IReadOnlyList<InboundApiKeyInfo>>([]));
Services.AddSingleton(_sites); Services.AddSingleton(_templates); Services.AddSingleton(_keys);
}
/// <summary>Each read failure leaves the other facts intact and is never a false zero.</summary>
[Theory]
[InlineData("Sites configured")]
[InlineData("Data connections configured")]
[InlineData("Templates")]
[InlineData("API keys")]
public void CountFailure_DoesNotEraseOtherFactsOrRenderZero(string label)
{
if(label=="Sites configured")_sites.GetAllSitesAsync().Returns(Task.FromException<IReadOnlyList<Site>>(new Exception("local failure")));
if(label=="Data connections configured")_sites.GetAllDataConnectionsAsync().Returns(Task.FromException<IReadOnlyList<DataConnection>>(new Exception("local failure")));
if(label=="Templates")_templates.GetTemplateStubsAsync().Returns(Task.FromException<IReadOnlyList<TemplateStub>>(new Exception("local failure")));
if(label=="API keys")_keys.ListAsync().Returns(Task.FromException<IReadOnlyList<InboundApiKeyInfo>>(new Exception("local failure")));
var cut=Render<DashboardPage>();
var facts=new Dictionary<string,string>{{"Sites configured","2"},{"Data connections configured","1"},{"Templates","3"},{"API keys","0"}};
foreach(var (name,count) in facts)
{
var fact=cut.Find("[role=region][aria-label='"+name+"']");
Assert.Contains(name==label?"Unavailable":count,fact.TextContent);
if(name==label)
{
Assert.Contains("Retry "+name,fact.TextContent);
Assert.DoesNotContain("0",fact.TextContent);
}
}
}
/// <summary>Only a failed API count is retried, and a real zero is displayed after success.</summary>
[Fact]
public void RetryFailure_PreservesSuccessfulFactsAndCanRecoverToZero()
{
_keys.ListAsync().Returns(Task.FromException<IReadOnlyList<InboundApiKeyInfo>>(new Exception("local failure")));
var cut=Render<DashboardPage>();
Assert.Contains("Unavailable",cut.Find("[aria-label='API keys']").TextContent);
_keys.ListAsync().Returns(Task.FromResult<IReadOnlyList<InboundApiKeyInfo>>([]));
cut.Find("[aria-label='API keys'] button").Click();
Assert.Contains("0",cut.Find("[aria-label='API keys']").TextContent);
Assert.DoesNotContain("Unavailable",cut.Markup);
_sites.Received(1).GetAllSitesAsync(); _sites.Received(1).GetAllDataConnectionsAsync(); _templates.Received(1).GetTemplateStubsAsync();
}
/// <summary>Early retries share the initial-read gate and duplicate retries remain single-flight.</summary>
[Fact]
public async Task RetryDuringNextRead_WaitsWithoutOverlapAndCoalescesDuplicateTarget()
{
var connectionRead = new TaskCompletionSource<IReadOnlyList<DataConnection>>(TaskCreationOptions.RunContinuationsAsynchronously);
_sites.GetAllSitesAsync().Returns(Task.FromException<IReadOnlyList<Site>>(new Exception("local failure")),
Task.FromResult<IReadOnlyList<Site>>([new("Recovered", "recovered")]));
_sites.GetAllDataConnectionsAsync().Returns(connectionRead.Task);
var cut = Render<DashboardPage>();
Assert.Contains("Unavailable", cut.Find("[aria-label='Sites configured']").TextContent);
Assert.Contains("Loading", cut.Find("[aria-label='Data connections configured']").TextContent);
// Model two already-dispatched retries without relying on a stale DOM node.
var retry = typeof(DashboardPage).GetMethod("LoadSites", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)!;
Task first = null!, second = null!;
await cut.InvokeAsync(() =>
{
first = (Task)retry.Invoke(cut.Instance, null)!;
second = (Task)retry.Invoke(cut.Instance, null)!;
});
Assert.Equal(1, _sites.ReceivedCalls().Count(c => c.GetMethodInfo().Name == nameof(ISiteRepository.GetAllSitesAsync)));
Assert.False(first.IsCompleted);
await cut.InvokeAsync(() => connectionRead.SetResult([new("Link", "OpcUa", 1)]));
await Task.WhenAll(first, second);
cut.WaitForAssertion(() => Assert.Contains("1", cut.Find("[aria-label='Sites configured']").TextContent));
Assert.Equal(2, _sites.ReceivedCalls().Count(c => c.GetMethodInfo().Name == nameof(ISiteRepository.GetAllSitesAsync)));
Assert.Equal(1, _sites.ReceivedCalls().Count(c => c.GetMethodInfo().Name == nameof(ISiteRepository.GetAllDataConnectionsAsync)));
}
/// <summary>An outstanding read remains loading while already loaded facts are available.</summary>
[Fact]
public async Task DelayedRead_RemainsLoadingUntilKnownZeroArrives()
{
var pending=new TaskCompletionSource<IReadOnlyList<InboundApiKeyInfo>>(TaskCreationOptions.RunContinuationsAsynchronously);
_keys.ListAsync().Returns(pending.Task);
var cut=Render<DashboardPage>();
Assert.Contains("Loading",cut.Find("[aria-label='API keys']").TextContent);
Assert.Contains("2",cut.Find("[aria-label='Sites configured']").TextContent);
await cut.InvokeAsync(()=>pending.SetResult([]));
cut.WaitForAssertion(()=>Assert.Contains("0",cut.Find("[aria-label='API keys']").TextContent));
Assert.DoesNotContain("Loading",cut.Find("[aria-label='API keys']").TextContent);
}
}
@@ -14,6 +14,20 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
/// </summary>
public class ToastNotificationTests : BunitContext
{
/// <summary>Dismissal names its toast and removes only that notification.</summary>
[Fact]
public async Task ToastDismiss_HasContextualNameAndPreservesOtherNotification()
{
var cut = Render<ToastNotification>();
await cut.InvokeAsync(() => cut.Instance.ShowError("Save failed", "Configuration", 60000));
await cut.InvokeAsync(() => cut.Instance.ShowInfo("Read completed", "Audit query", 60000));
var first = cut.FindAll(".toast").First(t => t.TextContent.Contains("Configuration"));
Assert.Equal("Dismiss Configuration", first.QuerySelector("button")!.GetAttribute("aria-label"));
await cut.InvokeAsync(() => first.QuerySelector("button")!.Click());
Assert.Single(cut.FindAll(".toast"));
Assert.Contains("Audit query", cut.Markup);
}
/// <summary>Verifies that show toast, when after disposal, is no op and schedules nothing.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]