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:
Joseph Doherty
2026-06-03 12:34:34 -04:00
parent c6d9b20d9f
commit bd6c0b4d3d
481 changed files with 2550 additions and 1668 deletions
@@ -47,6 +47,7 @@ public class AlarmsViewModelTests
}
/// <summary>Verifies that SubscribeCommand sets IsSubscribed flag.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeCommand_SetsIsSubscribed()
{
@@ -68,6 +69,7 @@ public class AlarmsViewModelTests
}
/// <summary>Verifies that UnsubscribeCommand clears IsSubscribed flag.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnsubscribeCommand_ClearsIsSubscribed()
{
@@ -81,6 +83,7 @@ public class AlarmsViewModelTests
}
/// <summary>Verifies that RefreshCommand calls the service.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task RefreshCommand_CallsService()
{
@@ -156,6 +159,7 @@ public class AlarmsViewModelTests
/// Regression test for Client.UI-006 — when SubscribeAlarmsAsync throws, the failure must be
/// surfaced to the operator via the view model's StatusMessage rather than silently swallowed.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Subscribe_OnFailure_SurfacesStatusMessage()
{
@@ -30,6 +30,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that LoadRootsAsync populates root nodes.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task LoadRootsAsync_PopulatesRootNodes()
{
@@ -41,6 +42,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that LoadRootsAsync browses with null parent.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task LoadRootsAsync_BrowsesWithNullParent()
{
@@ -61,6 +63,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that nodes with children have a placeholder.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task LoadRootsAsync_NodeWithChildren_HasPlaceholder()
{
@@ -73,6 +76,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that nodes without children have no placeholder.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task LoadRootsAsync_NodeWithoutChildren_HasNoPlaceholder()
{
@@ -84,6 +88,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that first tree node expand triggers child browse.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task TreeNode_FirstExpand_TriggersChildBrowse()
{
@@ -114,6 +119,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that second tree node expand does not browse again.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task TreeNode_SecondExpand_DoesNotBrowseAgain()
{
@@ -143,6 +149,7 @@ public class BrowseTreeViewModelTests
}
/// <summary>Verifies that IsLoading transitions during browse.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task TreeNode_IsLoading_TransitionsDuringBrowse()
{
@@ -136,13 +136,13 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
/// <inheritdoc />
public ConnectionInfo? CurrentConnectionInfo { get; set; }
/// <inheritdoc />
/// <summary>Raised when a subscribed node value changes.</summary>
public event EventHandler<DataChangedEventArgs>? DataChanged;
/// <inheritdoc />
/// <summary>Raised when an alarm condition event is received from the server.</summary>
public event EventHandler<AlarmEventArgs>? AlarmEvent;
/// <inheritdoc />
/// <summary>Raised when the OPC UA session connection state changes.</summary>
public event EventHandler<ConnectionStateChangedEventArgs>? ConnectionStateChanged;
/// <inheritdoc />
@@ -13,15 +13,14 @@ public sealed class FakeSettingsService : ISettingsService
/// <summary>Gets the last settings that were saved.</summary>
public UserSettings? LastSaved { get; private set; }
/// <summary>Loads and returns the current settings.</summary>
/// <inheritdoc />
public UserSettings Load()
{
LoadCallCount++;
return Settings;
}
/// <summary>Saves the specified settings.</summary>
/// <param name="settings">The settings to save.</param>
/// <inheritdoc />
public void Save(UserSettings settings)
{
SaveCallCount++;
@@ -60,6 +60,7 @@ public class HistoryViewModelTests
}
/// <summary>Verifies that a raw history read populates results correctly.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadHistoryCommand_Raw_PopulatesResults()
{
@@ -77,6 +78,7 @@ public class HistoryViewModelTests
}
/// <summary>Verifies that an aggregate history read populates results correctly.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadHistoryCommand_Aggregate_PopulatesResults()
{
@@ -94,6 +96,7 @@ public class HistoryViewModelTests
}
/// <summary>Verifies that the read history command clears previous results before loading new ones.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadHistoryCommand_ClearsResultsBefore()
{
@@ -107,6 +110,7 @@ public class HistoryViewModelTests
}
/// <summary>Verifies that the loading state is false after the read history command completes.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadHistoryCommand_IsLoading_FalseAfterComplete()
{
@@ -158,6 +162,7 @@ public class HistoryViewModelTests
}
/// <summary>Verifies that read history command errors are displayed in the results.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadHistoryCommand_Error_ShowsErrorInResults()
{
@@ -76,6 +76,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that a successful connect command updates the shell into the connected state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_TransitionsToConnected()
{
@@ -89,6 +90,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that the initial browse tree is loaded after a successful connect.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_LoadsRootNodes()
{
@@ -101,6 +103,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that redundancy details are fetched and exposed after connecting.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_FetchesRedundancyInfo()
{
@@ -114,6 +117,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that the session label shows the connected server and session identity.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_SetsSessionLabel()
{
@@ -126,6 +130,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that disconnect returns the shell to the disconnected state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task DisconnectCommand_TransitionsToDisconnected()
{
@@ -140,6 +145,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that disconnect clears session-specific UI state such as browse data and redundancy details.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Disconnect_ClearsStateAndChildren()
{
@@ -155,6 +161,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that connection-state events from the client update the shell status text and state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectionStateChangedEvent_UpdatesState()
{
@@ -171,6 +178,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that selecting a tree node updates the dependent read/write and history panels.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SelectedTreeNode_PropagatesToChildViewModels()
{
@@ -186,6 +194,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that a successful connect propagates connected state into the child tabs.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_PropagatesIsConnectedToChildViewModels()
{
@@ -200,6 +209,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that disconnect propagates disconnected state into the child tabs.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task DisconnectCommand_PropagatesIsConnectedFalseToChildViewModels()
{
@@ -215,6 +225,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that failed connection attempts restore the disconnected shell state and surface the error text.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectFailure_RevertsToDisconnected()
{
@@ -229,6 +240,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that connection-state transitions raise property-changed notifications for UI binding updates.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task PropertyChanged_FiredForConnectionState()
{
@@ -260,6 +272,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that failover endpoint text is parsed into connection settings on connect.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_MapsFailoverUrlsToSettings()
{
@@ -276,6 +289,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that empty failover text is normalized to no configured failover endpoints.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_MapsEmptyFailoverUrlsToNull()
{
@@ -289,6 +303,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that the configured session timeout is passed into the connection settings.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_MapsSessionTimeoutToSettings()
{
@@ -302,6 +317,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that the auto-accept certificate toggle is passed into the connection settings.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_MapsAutoAcceptCertificatesToSettings()
{
@@ -315,6 +331,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that a custom certificate store path is passed into the connection settings.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_MapsCertificateStorePathToSettings()
{
@@ -328,6 +345,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that subscribing selected nodes adds subscriptions and switches the shell to the subscriptions tab.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeSelectedNodesCommand_SubscribesAndSwitchesToTab()
{
@@ -348,6 +366,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that subscribing selected nodes is a no-op when nothing is selected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeSelectedNodesCommand_DoesNothing_WhenNoSelection()
{
@@ -361,6 +380,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that the history command targets the selected node and switches the shell to the history tab.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ViewHistoryForSelectedNodeCommand_SetsNodeAndSwitchesToTab()
{
@@ -378,6 +398,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that history actions are enabled when a variable node is selected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UpdateHistoryEnabledForSelection_TrueForVariableNode()
{
@@ -395,6 +416,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that history actions stay disabled when an object node rather than a variable is selected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UpdateHistoryEnabledForSelection_FalseForObjectNode()
{
@@ -470,6 +492,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that successful connections persist the current connection settings.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_SavesSettingsOnSuccess()
{
@@ -487,6 +510,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that failed connection attempts do not overwrite saved settings.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_DoesNotSaveOnFailure()
{
@@ -500,6 +524,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that active subscriptions are persisted when the shell disconnects.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_SavesSubscribedNodes()
{
@@ -522,6 +547,7 @@ public class MainWindowViewModelTests
/// view model must leave RedundancyInfo null without crashing or hiding the diagnostic.
/// The Status text is expected to remain "Connected" (redundancy is optional).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_RedundancyFailure_DoesNotBreakConnection()
{
@@ -538,6 +564,7 @@ public class MainWindowViewModelTests
/// <summary>
/// Verifies that saved subscriptions are restored after reconnecting the shell.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectCommand_RestoresSavedSubscriptions()
{
@@ -51,6 +51,7 @@ public class ReadWriteViewModelTests
}
/// <summary>Verifies that the read command updates value and status.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadCommand_UpdatesValueAndStatus()
{
@@ -91,6 +92,7 @@ public class ReadWriteViewModelTests
}
/// <summary>Verifies that the write command updates write status.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteCommand_UpdatesWriteStatus()
{
@@ -118,6 +120,7 @@ public class ReadWriteViewModelTests
}
/// <summary>Verifies that read command error sets error status.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadCommand_Error_SetsErrorStatus()
{
@@ -41,6 +41,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionCommand adds a new subscription to the active list.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionCommand_AddsItem()
{
@@ -58,6 +59,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that RemoveSubscriptionCommand removes selected subscription.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task RemoveSubscriptionCommand_RemovesItem()
{
@@ -83,6 +85,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that DataChanged event updates the matching subscription row.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task DataChanged_UpdatesMatchingRow()
{
@@ -98,6 +101,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that DataChanged event does not update non-matching subscription rows.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task DataChanged_DoesNotUpdateNonMatchingRow()
{
@@ -146,6 +150,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionForNodeAsync adds a subscription.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionForNodeAsync_AddsSubscription()
{
@@ -160,6 +165,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionForNodeAsync skips duplicate subscriptions.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionForNodeAsync_SkipsDuplicate()
{
@@ -173,6 +179,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionForNodeAsync does nothing when disconnected.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionForNodeAsync_DoesNothing_WhenDisconnected()
{
@@ -185,6 +192,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that GetSubscribedNodeIds returns all active subscription node IDs.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task GetSubscribedNodeIds_ReturnsActiveNodeIds()
{
@@ -200,6 +208,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that RestoreSubscriptionsAsync subscribes to all provided node IDs.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task RestoreSubscriptionsAsync_SubscribesAllNodes()
{
@@ -212,6 +221,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that ValidateAndWriteAsync returns true on successful write.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task ValidateAndWriteAsync_SuccessReturnsTrue()
{
@@ -227,6 +237,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that ValidateAndWriteAsync returns false when value parsing fails.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task ValidateAndWriteAsync_ParseFailureReturnsFalse()
{
@@ -242,6 +253,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that ValidateAndWriteAsync returns false when write fails.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task ValidateAndWriteAsync_WriteFailureReturnsFalse()
{
@@ -256,6 +268,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that ValidateAndWriteAsync returns false when status is bad.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task ValidateAndWriteAsync_BadStatusReturnsFalse()
{
@@ -270,6 +283,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionRecursiveAsync subscribes a variable directly.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionRecursiveAsync_SubscribesVariableDirectly()
{
@@ -282,6 +296,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionRecursiveAsync browses objects and subscribes variable children.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionRecursiveAsync_BrowsesObjectAndSubscribesVariableChildren()
{
@@ -302,6 +317,7 @@ public class SubscriptionsViewModelTests
/// Regression test for Client.UI-006 — when SubscribeAsync throws, the failure must be surfaced
/// to the operator via the view model's StatusMessage rather than silently swallowed.
/// </summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscription_OnFailure_SurfacesStatusMessage()
{
@@ -320,6 +336,7 @@ public class SubscriptionsViewModelTests
/// Regression test for Client.UI-006 — silent swallow when adding a subscription for a node
/// (the context-menu helper) must also surface a status to the operator.
/// </summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionForNodeAsync_OnFailure_SurfacesStatusMessage()
{
@@ -334,6 +351,7 @@ public class SubscriptionsViewModelTests
}
/// <summary>Verifies that AddSubscriptionRecursiveAsync recurses through nested objects.</summary>
/// <returns>A task that represents the asynchronous test operation.</returns>
[Fact]
public async Task AddSubscriptionRecursiveAsync_RecursesNestedObjects()
{