docs: complete XML doc comments via fixdocs (2757 to 131 findings)
Add missing <returns>/<param>/<summary>/<typeparam> tags and clean up misused inheritdoc across 481 files so the documented API surface is complete. Documentation-only (zero code lines changed). The 131 remaining findings are inheritdoc-style warnings deliberately left to preserve hand-written implementation rationale (plan-decision notes, race-condition explanations).
This commit is contained in:
@@ -21,6 +21,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that serializing and deserializing an <see cref="AbCipDriverOptions"/> round-trip preserves all known fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -71,6 +72,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.Tags[0].DataType.ShouldBe(AbCipDataType.Real);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserializing JSON with unknown fields drops them without error.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -86,6 +88,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(10);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a device row round-trips correctly through its definition.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -101,6 +104,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("PLC-A");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that editing one field of a device row preserves all other fields.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -116,6 +120,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.ConnectionSize.ShouldBe(4002);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a tag row round-trips correctly through its definition.</summary>
|
||||
[Fact]
|
||||
public void TagRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -134,6 +139,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.Writable.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that editing one field of a tag row preserves all other fields.</summary>
|
||||
[Fact]
|
||||
public void TagRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -154,6 +160,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
back.Members[0].Name.ShouldBe("Sub");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device row validation rejects a duplicate host address.</summary>
|
||||
[Fact]
|
||||
public void ValidateDeviceRow_rejects_duplicate_host()
|
||||
{
|
||||
@@ -162,6 +169,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag row validation rejects a duplicate tag name.</summary>
|
||||
[Fact]
|
||||
public void ValidateTagRow_rejects_duplicate_name()
|
||||
{
|
||||
@@ -170,6 +178,7 @@ public sealed class AbCipDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device and tag lists survive a full options serialize/deserialize round-trip.</summary>
|
||||
[Fact]
|
||||
public void Device_and_tag_lists_survive_options_serialize_round_trip()
|
||||
{
|
||||
|
||||
+9
@@ -22,6 +22,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that round-trip serialization preserves all known fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -71,6 +72,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.Tags[1].DataType.ShouldBe(AbLegacyDataType.Bit);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserialization silently drops unknown fields.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -86,6 +88,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(10);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a device row round-trips through its definition.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -101,6 +104,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("PLC-A");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a device row preserves unedited fields when converting back to definition.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -114,6 +118,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("PLC-A");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a tag row round-trips through its definition.</summary>
|
||||
[Fact]
|
||||
public void TagRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -132,6 +137,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.Writable.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a tag row preserves unedited fields when converting back to definition.</summary>
|
||||
[Fact]
|
||||
public void TagRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -146,6 +152,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
back.WriteIdempotent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device row validation rejects a duplicate host address.</summary>
|
||||
[Fact]
|
||||
public void ValidateDeviceRow_rejects_duplicate_host()
|
||||
{
|
||||
@@ -154,6 +161,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag row validation rejects a duplicate tag name.</summary>
|
||||
[Fact]
|
||||
public void ValidateTagRow_rejects_duplicate_name()
|
||||
{
|
||||
@@ -162,6 +170,7 @@ public sealed class AbLegacyDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device and tag lists survive a full options serialization round-trip.</summary>
|
||||
[Fact]
|
||||
public void Device_and_tag_lists_survive_options_serialize_round_trip()
|
||||
{
|
||||
|
||||
@@ -14,6 +14,8 @@ public sealed class BrowseSessionReaperTests
|
||||
private static BrowseSessionReaper NewReaper(BrowseSessionRegistry registry) =>
|
||||
new(registry, NullLogger<BrowseSessionReaper>.Instance);
|
||||
|
||||
/// <summary>Verifies that ReapOnceAsync evicts a session that has been idle beyond the timeout.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReapOnceAsync_evicts_idle_session()
|
||||
{
|
||||
@@ -31,6 +33,8 @@ public sealed class BrowseSessionReaperTests
|
||||
session.Disposed.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReapOnceAsync preserves a recently used session.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReapOnceAsync_preserves_recent_session()
|
||||
{
|
||||
@@ -45,6 +49,8 @@ public sealed class BrowseSessionReaperTests
|
||||
session.Disposed.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReapOnceAsync handles a session already removed from the registry without throwing.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReapOnceAsync_handles_already_removed_session()
|
||||
{
|
||||
@@ -65,6 +71,8 @@ public sealed class BrowseSessionReaperTests
|
||||
session.Disposed.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReapOnceAsync continues processing remaining sessions when one session's dispose throws.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReapOnceAsync_continues_when_one_session_dispose_throws()
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Browsing;
|
||||
/// concurrent-registration behaviour.</summary>
|
||||
public sealed class BrowseSessionRegistryTests
|
||||
{
|
||||
/// <summary>Verifies that a registered session can be retrieved by its token.</summary>
|
||||
[Fact]
|
||||
public void Register_then_TryGet_returns_session()
|
||||
{
|
||||
@@ -22,6 +23,7 @@ public sealed class BrowseSessionRegistryTests
|
||||
got.ShouldBeSameAs((IBrowseSession)session);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that looking up an unknown token returns false.</summary>
|
||||
[Fact]
|
||||
public void TryGet_unknown_returns_false()
|
||||
{
|
||||
@@ -31,6 +33,7 @@ public sealed class BrowseSessionRegistryTests
|
||||
got.ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a removed session can no longer be retrieved.</summary>
|
||||
[Fact]
|
||||
public void TryRemove_then_TryGet_returns_false()
|
||||
{
|
||||
@@ -43,6 +46,8 @@ public sealed class BrowseSessionRegistryTests
|
||||
registry.TryGet(session.Token, out _).ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that concurrent registrations from many tasks are all visible in the snapshot.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task Concurrent_Register_from_many_tasks_all_visible_in_Snapshot()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,8 @@ public sealed class BrowserSessionServiceTests
|
||||
BrowseSessionRegistry registry, params IDriverBrowser[] browsers) =>
|
||||
new(browsers, registry, NullLogger<BrowserSessionService>.Instance);
|
||||
|
||||
/// <summary>Verifies that OpenAsync returns Ok=false with a message when the driver type is unknown.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task OpenAsync_unknown_driver_type_returns_Ok_false_with_message()
|
||||
{
|
||||
@@ -29,6 +31,8 @@ public sealed class BrowserSessionServiceTests
|
||||
result.Message!.ShouldContain("Unknown");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that OpenAsync returns a token and registers the session on the happy path.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task OpenAsync_happy_path_returns_token_and_registers()
|
||||
{
|
||||
@@ -50,6 +54,8 @@ public sealed class BrowserSessionServiceTests
|
||||
registered.ShouldBeSameAs((IBrowseSession)session);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that OpenAsync swallows driver exceptions and returns Ok=false.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task OpenAsync_swallows_driver_throws_returns_Ok_false()
|
||||
{
|
||||
@@ -68,6 +74,8 @@ public sealed class BrowserSessionServiceTests
|
||||
result.Message!.ShouldContain("boom");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that RootAsync throws BrowseSessionNotFoundException for an unknown token.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task RootAsync_unknown_token_throws_BrowseSessionNotFoundException()
|
||||
{
|
||||
@@ -78,6 +86,8 @@ public sealed class BrowserSessionServiceTests
|
||||
() => service.RootAsync(Guid.NewGuid(), CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that RootAsync invokes the session Root method and returns its result.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task RootAsync_invokes_session_Root()
|
||||
{
|
||||
@@ -96,6 +106,8 @@ public sealed class BrowserSessionServiceTests
|
||||
actual.ShouldBe(expected);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that RootAsync cancels the call when the per-call timeout elapses.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task RootAsync_enforces_PerCallTimeout()
|
||||
{
|
||||
@@ -118,6 +130,8 @@ public sealed class BrowserSessionServiceTests
|
||||
sw.Elapsed.ShouldBeLessThan(TimeSpan.FromSeconds(35));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that CloseAsync removes the session from the registry and disposes it.</summary>
|
||||
/// <returns>A task that represents the asynchronous test operation.</returns>
|
||||
[Fact]
|
||||
public async Task CloseAsync_removes_and_disposes_session()
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ internal sealed class FakeBrowseSession : IBrowseSession
|
||||
/// <inheritdoc />
|
||||
public Guid Token { get; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>Mutable so tests can rewind the timestamp into the reaper's eviction window.</summary>
|
||||
/// <inheritdoc />
|
||||
public DateTime LastUsedUtc { get; set; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>True once <see cref="DisposeAsync"/> has run to completion.</summary>
|
||||
@@ -40,7 +40,8 @@ internal sealed class FakeBrowseSession : IBrowseSession
|
||||
public Task<IReadOnlyList<AttributeInfo>> AttributesAsync(string nodeId, CancellationToken ct)
|
||||
=> AttributesHandler?.Invoke(nodeId, ct) ?? Task.FromResult<IReadOnlyList<AttributeInfo>>(Array.Empty<AttributeInfo>());
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Disposes the fake browse session asynchronously, recording completion or throwing if configured.</summary>
|
||||
/// <returns>A completed value task.</returns>
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
if (ThrowOnDispose) throw new InvalidOperationException("dispose-failed");
|
||||
|
||||
@@ -17,6 +17,7 @@ public sealed class DriverStatusSnapshotStoreTests
|
||||
private static DriverHealthChanged Snap(string instance, string state = "Healthy") =>
|
||||
new("MAIN", instance, state, null, null, 0, new DateTime(2026, 5, 29, 0, 0, 0, DateTimeKind.Utc));
|
||||
|
||||
/// <summary>Verifies that Upsert raises SnapshotChanged with the stored snapshot.</summary>
|
||||
[Fact]
|
||||
public void Upsert_raises_SnapshotChanged_with_the_stored_snapshot()
|
||||
{
|
||||
@@ -31,6 +32,7 @@ public sealed class DriverStatusSnapshotStoreTests
|
||||
received[0].ShouldBeSameAs(snap);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Upsert then TryGet returns the latest snapshot.</summary>
|
||||
[Fact]
|
||||
public void Upsert_then_TryGet_returns_the_latest_snapshot()
|
||||
{
|
||||
@@ -42,6 +44,7 @@ public sealed class DriverStatusSnapshotStoreTests
|
||||
latest.State.ShouldBe("Degraded");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an unsubscribed handler stops receiving events after removal.</summary>
|
||||
[Fact]
|
||||
public void Unsubscribed_handler_stops_receiving_after_removal()
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that a round-trip serialization preserves all known FOCAS driver option fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -76,6 +77,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.Tags.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserialization silently drops unknown fields without throwing.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -89,6 +91,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(18);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the form model round-trip preserves all editable FOCAS driver option fields.</summary>
|
||||
[Fact]
|
||||
public void FormModel_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -140,6 +143,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
roundTripped.FixedTree.TimerPollInterval.ShouldBe(TimeSpan.FromSeconds(45));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a FocasDeviceRow round-trips correctly through its definition type.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -155,6 +159,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("CNC1");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that FocasDeviceRow preserves unedited fields when converting to and from a definition.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -168,6 +173,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.Series.ShouldBe(FocasCncSeries.Thirty_i);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a FocasTagRow round-trips correctly through its definition type.</summary>
|
||||
[Fact]
|
||||
public void TagRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -186,6 +192,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.Writable.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that FocasTagRow preserves unedited fields when converting to a definition.</summary>
|
||||
[Fact]
|
||||
public void TagRow_preserves_unedited_fields()
|
||||
{
|
||||
@@ -200,6 +207,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
back.WriteIdempotent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device row validation rejects a duplicate host address.</summary>
|
||||
[Fact]
|
||||
public void ValidateDeviceRow_rejects_duplicate_host()
|
||||
{
|
||||
@@ -208,6 +216,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag row validation rejects a duplicate tag name.</summary>
|
||||
[Fact]
|
||||
public void ValidateTagRow_rejects_duplicate_name()
|
||||
{
|
||||
@@ -216,6 +225,7 @@ public sealed class FocasDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device and tag lists survive a full options serialization round-trip.</summary>
|
||||
[Fact]
|
||||
public void Device_and_tag_lists_survive_options_serialize_round_trip()
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
WriteIndented = false,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that a round-trip serialization preserves all known fields of GalaxyDriverOptions.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -76,6 +77,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(45);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserialization silently drops unknown fields from the JSON input.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
|
||||
+4
@@ -15,6 +15,7 @@ public sealed class HistorianWonderwareDriverPageFormSerializationTests
|
||||
WriteIndented = false,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that a round-trip serialization/deserialization preserves all known fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -42,6 +43,7 @@ public sealed class HistorianWonderwareDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(25);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that null timeout values fall back to the expected defaults after deserialization.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_NullTimeouts_UsesDefaults()
|
||||
{
|
||||
@@ -59,6 +61,7 @@ public sealed class HistorianWonderwareDriverPageFormSerializationTests
|
||||
back.EffectiveCallTimeout.ShouldBe(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unknown JSON properties are silently ignored during deserialization.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -82,6 +85,7 @@ public sealed class HistorianWonderwareDriverPageFormSerializationTests
|
||||
back.PipeName.ShouldBe("otopcua-historian");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the form model FromRecord/ToRecord round-trip preserves all fields losslessly.</summary>
|
||||
[Fact]
|
||||
public void FormModel_RoundTrip_PreservesAllFields()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests;
|
||||
/// </summary>
|
||||
public sealed class InProcessBroadcasterTests
|
||||
{
|
||||
/// <summary>Verifies that Publish raises the Received event for all current subscribers.</summary>
|
||||
[Fact]
|
||||
public void Publish_raises_Received_for_all_current_subscribers()
|
||||
{
|
||||
@@ -27,6 +28,7 @@ public sealed class InProcessBroadcasterTests
|
||||
b.ShouldBe(["evt-1"]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an unsubscribed handler stops receiving events after removal.</summary>
|
||||
[Fact]
|
||||
public void Unsubscribed_handler_stops_receiving()
|
||||
{
|
||||
@@ -42,6 +44,7 @@ public sealed class InProcessBroadcasterTests
|
||||
received.ShouldBe(["first"]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Publish with no subscribers does not throw an exception.</summary>
|
||||
[Fact]
|
||||
public void Publish_with_no_subscribers_does_not_throw()
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that round-trip serialization preserves all known Modbus driver fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -97,6 +98,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(10);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserialization silently drops unknown Modbus driver fields.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -112,6 +114,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(10);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a tag row round-trips through its definition.</summary>
|
||||
[Fact]
|
||||
public void TagRow_round_trips_through_definition()
|
||||
{
|
||||
@@ -129,6 +132,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
back.Writable.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the tag list survives a full options serialization round-trip.</summary>
|
||||
[Fact]
|
||||
public void Tag_list_survives_options_serialize_round_trip()
|
||||
{
|
||||
@@ -144,6 +148,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
back.Tags[0].Name.ShouldBe("A");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag row validation rejects a duplicate tag name.</summary>
|
||||
[Fact]
|
||||
public void ValidateRow_rejects_duplicate_name()
|
||||
{
|
||||
@@ -152,6 +157,7 @@ public sealed class ModbusDriverPageFormSerializationTests
|
||||
.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that converting a tag row to a definition preserves unedited fields.</summary>
|
||||
[Fact]
|
||||
public void ToDefinition_preserves_unedited_fields()
|
||||
{
|
||||
|
||||
+9
@@ -17,6 +17,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
WriteIndented = false,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that a round-trip serialization preserves all known driver option fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -68,6 +69,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(20);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserialization silently drops unknown fields.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -83,6 +85,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(20);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the form model round-trip preserves all driver option fields.</summary>
|
||||
[Fact]
|
||||
public void FormModel_RoundTrip_PreservesAllFields()
|
||||
{
|
||||
@@ -156,6 +159,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
result.ProbeTimeoutSeconds.ShouldBe(25);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that EndpointUrlRow.ToUrl trims leading and trailing whitespace.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrlRow_FromUrl_ToUrl_Trims()
|
||||
{
|
||||
@@ -165,6 +169,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
row.ToUrl().ShouldBe("opc.tcp://plc:4840");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ValidateRow rejects a blank URL.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrlRow_ValidateRow_RejectsBlank()
|
||||
{
|
||||
@@ -176,6 +181,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
error.ShouldBe("URL is required.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ValidateRow rejects a URL with a non-opc.tcp scheme.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrlRow_ValidateRow_RejectsNonOpcTcpScheme()
|
||||
{
|
||||
@@ -187,6 +193,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
error.ShouldBe("Endpoint URL must start with opc.tcp://");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ValidateRow rejects a duplicate URL.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrlRow_ValidateRow_RejectsDuplicate()
|
||||
{
|
||||
@@ -204,6 +211,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
error.ShouldContain("Duplicate endpoint");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that editing a row in-place does not flag it as a duplicate of itself.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrlRow_ValidateRow_AllowsEditingRowInPlace()
|
||||
{
|
||||
@@ -220,6 +228,7 @@ public sealed class OpcUaClientDriverPageFormSerializationTests
|
||||
error.ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an endpoint URL list round-trips and preserves the original order.</summary>
|
||||
[Fact]
|
||||
public void EndpointUrls_ListRoundTrip_PreservesOrder()
|
||||
{
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
|
||||
|
||||
public sealed class AbLegacyAddressBuilderTests
|
||||
{
|
||||
/// <summary>Verifies that Build_Canonical returns the expected canonical address string for each file type.</summary>
|
||||
/// <param name="fileType">The file type letter (e.g., N, B, F).</param>
|
||||
/// <param name="fileNumber">The file number.</param>
|
||||
/// <param name="element">The element index within the file.</param>
|
||||
/// <param name="expected">The expected canonical address string.</param>
|
||||
[Theory]
|
||||
[InlineData("N", 7, 0, "N7:0")]
|
||||
[InlineData("B", 3, 1, "B3:1")]
|
||||
|
||||
@@ -6,6 +6,10 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
|
||||
|
||||
public sealed class FocasAddressBuilderTests
|
||||
{
|
||||
/// <summary>Verifies that Build produces the canonical group:parameterId address string.</summary>
|
||||
/// <param name="group">The FOCAS parameter group name.</param>
|
||||
/// <param name="parameterId">The FOCAS parameter ID.</param>
|
||||
/// <param name="expected">The expected canonical address string.</param>
|
||||
[Theory]
|
||||
[InlineData("axis", 5, "axis:5")]
|
||||
[InlineData("spindle", 0, "spindle:0")]
|
||||
|
||||
+5
@@ -6,6 +6,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
|
||||
|
||||
public sealed class HistorianWonderwareAddressBuilderTests
|
||||
{
|
||||
/// <summary>Verifies that Build produces the canonical address query string for various tag/mode/interval combinations.</summary>
|
||||
/// <param name="tag">The tag name input.</param>
|
||||
/// <param name="mode">The retrieval mode input.</param>
|
||||
/// <param name="interval">The interval input.</param>
|
||||
/// <param name="expected">The expected canonical address string.</param>
|
||||
[Theory]
|
||||
[InlineData("SysTimeHour", "Cyclic", 60, "SysTimeHour?mode=Cyclic&interval=60")]
|
||||
[InlineData("ReactorTemp", "Last", 1, "ReactorTemp?mode=Last&interval=1")]
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
|
||||
|
||||
public sealed class ModbusAddressBuilderTests
|
||||
{
|
||||
/// <summary>Verifies that Build produces canonical Modbus address strings for all supported register types.</summary>
|
||||
/// <param name="type">The Modbus register type.</param>
|
||||
/// <param name="offset">The register offset.</param>
|
||||
/// <param name="length">The data length.</param>
|
||||
/// <param name="expected">The expected canonical address string.</param>
|
||||
[Theory]
|
||||
[InlineData("Holding", 1, 1, "4x00001-1")]
|
||||
[InlineData("Coil", 0, 1, "0x00000-1")]
|
||||
@@ -15,6 +20,7 @@ public sealed class ModbusAddressBuilderTests
|
||||
public void Build_Canonical(string type, int offset, int length, string expected)
|
||||
=> ModbusAddressBuilder.Build(type, offset, length).ShouldBe(expected);
|
||||
|
||||
/// <summary>Verifies that Build falls back to the Holding register type for unknown type strings.</summary>
|
||||
[Fact]
|
||||
public void Build_UnknownType_FallsBackToHolding()
|
||||
=> ModbusAddressBuilder.Build("Unknown", 1, 1).ShouldBe("4x00001-1");
|
||||
|
||||
@@ -6,6 +6,12 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
|
||||
|
||||
public sealed class S7AddressBuilderTests
|
||||
{
|
||||
/// <summary>Verifies that Build produces the canonical S7 address string for all supported areas and types.</summary>
|
||||
/// <param name="area">The S7 memory area (DB / M / I / Q).</param>
|
||||
/// <param name="dbNumber">The DB number (relevant only for the DB area).</param>
|
||||
/// <param name="offset">The byte offset within the area.</param>
|
||||
/// <param name="s7Type">The S7 data type qualifier (X / B / W / D / REAL).</param>
|
||||
/// <param name="expected">The expected canonical address string.</param>
|
||||
[Theory]
|
||||
[InlineData("DB", 10, 20, "REAL", "DB10.DBD20:REAL")]
|
||||
[InlineData("DB", 1, 0, "X", "DB1.DBX0.0:X")]
|
||||
|
||||
@@ -6,10 +6,12 @@ using ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
||||
|
||||
public class ResilienceFormModelTests
|
||||
{
|
||||
/// <summary>Verifies that a blank form model serializes to null JSON.</summary>
|
||||
[Fact]
|
||||
public void Blank_form_serializes_to_null()
|
||||
=> new ResilienceFormModel().ToJson().ShouldBeNull();
|
||||
|
||||
/// <summary>Verifies that a partial policy override round-trips correctly through JSON.</summary>
|
||||
[Fact]
|
||||
public void Partial_override_round_trips()
|
||||
{
|
||||
@@ -26,6 +28,7 @@ public class ResilienceFormModelTests
|
||||
back.Policies["Write"].IsEmpty.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that malformed JSON input yields an empty model with no-error handling.</summary>
|
||||
[Fact]
|
||||
public void Malformed_json_yields_empty_model()
|
||||
{
|
||||
@@ -34,6 +37,7 @@ public class ResilienceFormModelTests
|
||||
m.Policies["Read"].IsEmpty.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that JSON emitted by the form model can be parsed by the runtime resilience options parser.</summary>
|
||||
[Fact]
|
||||
public void Emitted_json_is_consumable_by_the_runtime_parser()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
WriteIndented = false,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that serializing and deserializing S7 driver options preserves all known fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -54,6 +55,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
back.Tags.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserializing JSON with unknown fields silently drops the unrecognized members.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -67,6 +69,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(12);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the S7 form model round-trip preserves all editable fields including tags.</summary>
|
||||
[Fact]
|
||||
public void FormModel_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -122,6 +125,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
roundTripped.Tags[1].Writable.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an S7 tag row round-trip preserves all editable fields.</summary>
|
||||
[Fact]
|
||||
public void S7TagRow_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -137,6 +141,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
back.StringLength.ShouldBe(80);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unedited fields are carried through after an S7 tag row edit.</summary>
|
||||
[Fact]
|
||||
public void S7TagRow_CarriesThroughUneditedFields()
|
||||
{
|
||||
@@ -154,6 +159,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
back.WriteIdempotent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that S7 tag row validation rejects duplicate tag names.</summary>
|
||||
[Fact]
|
||||
public void S7TagRow_ValidateRow_RejectsDuplicateNames()
|
||||
{
|
||||
@@ -180,6 +186,7 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
S7DriverPage.S7TagRow.ValidateRow(ok, all, editIndex: 1).ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the tag list serialize round-trip preserves all tag definitions.</summary>
|
||||
[Fact]
|
||||
public void TagList_SerializeRoundTrip_PreservesTags()
|
||||
{
|
||||
|
||||
+10
@@ -14,6 +14,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
WriteIndented = false,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that serializing and deserializing TwinCAT driver options preserves all known fields.</summary>
|
||||
[Fact]
|
||||
public void RoundTrip_PreservesKnownFields()
|
||||
{
|
||||
@@ -51,6 +52,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.Tags.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that deserializing JSON with unknown fields silently drops the unrecognized members.</summary>
|
||||
[Fact]
|
||||
public void Deserialize_DropsUnknownFields()
|
||||
{
|
||||
@@ -64,6 +66,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.ProbeTimeoutSeconds.ShouldBe(25);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the form model round-trip preserves all editable fields.</summary>
|
||||
[Fact]
|
||||
public void FormModel_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -96,6 +99,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
roundTripped.ProbeTimeoutSeconds.ShouldBe(15);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a device row round-trip preserves all editable fields.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -109,6 +113,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("PLC1");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unedited source fields are carried through after a device row edit.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_CarriesThroughUneditedSourceFields()
|
||||
{
|
||||
@@ -124,6 +129,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.DeviceName.ShouldBe("Renamed");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that device row validation rejects duplicate host addresses.</summary>
|
||||
[Fact]
|
||||
public void DeviceRow_ValidateRow_RejectsDuplicateHostAddress()
|
||||
{
|
||||
@@ -140,6 +146,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
error.ShouldContain("Duplicate");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a tag row round-trip preserves all editable fields.</summary>
|
||||
[Fact]
|
||||
public void TagRow_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
@@ -156,6 +163,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.Writable.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the unedited WriteIdempotent field is carried through after a tag row edit.</summary>
|
||||
[Fact]
|
||||
public void TagRow_CarriesThroughUneditedWriteIdempotent()
|
||||
{
|
||||
@@ -172,6 +180,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
back.WriteIdempotent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that tag row validation rejects duplicate tag names (case-insensitive).</summary>
|
||||
[Fact]
|
||||
public void TagRow_ValidateRow_RejectsDuplicateName()
|
||||
{
|
||||
@@ -189,6 +198,7 @@ public sealed class TwinCATDriverPageFormSerializationTests
|
||||
error.ShouldContain("Duplicate");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ToOptions serializes device and tag lists correctly.</summary>
|
||||
[Fact]
|
||||
public void FormModel_ToOptions_SerializesDeviceAndTagLists()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests;
|
||||
|
||||
public sealed class _PlaceholderTests
|
||||
{
|
||||
/// <summary>Verifies the project compiles and the test runner can discover test methods.</summary>
|
||||
[Fact]
|
||||
public void ProjectCompilesAndTestRunnerDiscoversIt() => 1.ShouldBe(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user