using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol; using ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters; namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests; /// /// M7-B2 (T15): serves a small canned address-space /// tree so DCL browse/paging flows can be exercised without a live OPC UA server. /// The stub also fakes BrowseNext continuation paging on Folder1 so the /// continuation-token round-trip is testable end-to-end against the contract. /// public class StubOpcUaClientBrowseTests { // StubOpcUaClient is internal; reached here via InternalsVisibleTo on the // DataConnectionLayer assembly (the test project is already a friend, since // other tests in this project new up internal adapter types). private static async Task ConnectedStubAsync() { var client = new StubOpcUaClient(); await client.ConnectAsync("opc.tcp://stub", null, CancellationToken.None); return client; } [Fact] public async Task BrowseRoot_ReturnsTwoFolders_NoContinuation() { await using var client = (StubOpcUaClient)await ConnectedStubAsync(); var result = await client.BrowseChildrenAsync(parentNodeId: null); Assert.False(result.Truncated); Assert.Null(result.ContinuationToken); Assert.Collection( result.Children, n => { Assert.Equal("Folder1", n.DisplayName); Assert.Equal(BrowseNodeClass.Object, n.NodeClass); Assert.True(n.HasChildren); }, n => { Assert.Equal("Folder2", n.DisplayName); Assert.Equal(BrowseNodeClass.Object, n.NodeClass); Assert.False(n.HasChildren); }); } [Fact] public async Task BrowseFolder1_NoToken_ReturnsTag1_AndContinuationToken() { await using var client = (StubOpcUaClient)await ConnectedStubAsync(); var result = await client.BrowseChildrenAsync(parentNodeId: "Folder1"); Assert.True(result.Truncated); Assert.Equal("STUB_PAGE2", result.ContinuationToken); var only = Assert.Single(result.Children); Assert.Equal("Tag1", only.DisplayName); Assert.Equal(BrowseNodeClass.Variable, only.NodeClass); Assert.False(only.HasChildren); } [Fact] public async Task BrowseFolder1_WithContinuationToken_ReturnsTag2_AndNoFurtherContinuation() { await using var client = (StubOpcUaClient)await ConnectedStubAsync(); var result = await client.BrowseChildrenAsync( parentNodeId: "Folder1", continuationToken: "STUB_PAGE2"); Assert.False(result.Truncated); Assert.Null(result.ContinuationToken); var only = Assert.Single(result.Children); Assert.Equal("Tag2", only.DisplayName); Assert.Equal(BrowseNodeClass.Variable, only.NodeClass); Assert.False(only.HasChildren); } [Fact] public async Task BrowseLeaf_ReturnsEmpty_NoContinuation() { await using var client = (StubOpcUaClient)await ConnectedStubAsync(); var result = await client.BrowseChildrenAsync(parentNodeId: "Folder2"); Assert.False(result.Truncated); Assert.Null(result.ContinuationToken); Assert.Empty(result.Children); } }