|
15 | 15 | using Kepware.Api.Test.ApiClient; |
16 | 16 | using Kepware.Api.Util; |
17 | 17 | using Shouldly; |
| 18 | +using Xunit.Sdk; |
18 | 19 |
|
19 | 20 | namespace Kepware.Api.Test.ApiClient |
20 | 21 | { |
@@ -98,7 +99,7 @@ public async Task LoadProject_ShouldLoadCorrectly_BasedOnProductSupport( |
98 | 99 | await ConfigureToServeEndpoints(); |
99 | 100 | } |
100 | 101 |
|
101 | | - var project = await _kepwareApiClient.Project.LoadProjectAsync(true); |
| 102 | + var project = await _kepwareApiClient.Project.LoadProjectAsync(blnLoadFullProject: true); |
102 | 103 |
|
103 | 104 | project.IsLoadedByProjectLoadService.ShouldBe(supportsJsonLoad); |
104 | 105 |
|
@@ -140,6 +141,71 @@ public async Task LoadProject_ShouldLoadCorrectly_BasedOnProductSupport( |
140 | 141 | } |
141 | 142 | } |
142 | 143 |
|
| 144 | + [Theory] |
| 145 | + [InlineData("KEPServerEX", "12", 6, 17, true)] |
| 146 | + [InlineData("ThingWorxKepwareServer", "12", 6, 17, true)] |
| 147 | + [InlineData("ThingWorxKepwareEdge", "13", 1, 10, true)] |
| 148 | + [InlineData("Kepware Edge", "13", 1, 0, true)] |
| 149 | + public async Task LoadProject_ShouldLoadCorrectly_Serialize_BasedOnProductSupport( |
| 150 | + string productName, string productId, int majorVersion, int minorVersion, bool supportsJsonLoad) |
| 151 | + { |
| 152 | + ConfigureConnectedClient(productName, productId, majorVersion, minorVersion); |
| 153 | + |
| 154 | + if (supportsJsonLoad) |
| 155 | + { |
| 156 | + await ConfigureToServeEndpoints(); |
| 157 | + } |
| 158 | + else |
| 159 | + { |
| 160 | + // Skip this test case at runtime because it expects the server to serve a full JSON project. |
| 161 | + throw SkipException.ForSkip($"Product {productName} v{majorVersion}.{minorVersion} (id={productId}) does not support JSON project load. Skipping full-project test case."); |
| 162 | + } |
| 163 | + |
| 164 | + var tagLimitOverride = 100; // Set a high tag limit to ensure all tags are loaded for comparison |
| 165 | + |
| 166 | + var project = await _kepwareApiClient.Project.LoadProjectAsync(blnLoadFullProject: true, projectLoadTagLimit: tagLimitOverride); |
| 167 | + |
| 168 | + // Optimized recursion is done for this test, which will result in false. |
| 169 | + project.IsLoadedByProjectLoadService.ShouldBeFalse(); |
| 170 | + |
| 171 | + project.ShouldNotBeNull(); |
| 172 | + project.Channels.ShouldNotBeEmpty("Channels list should not be empty."); |
| 173 | + |
| 174 | + var testProject = await LoadJsonTestDataAsync(); |
| 175 | + var compareResult = EntityCompare.Compare<ChannelCollection, Channel>(testProject?.Project?.Channels, project?.Channels); |
| 176 | + |
| 177 | + compareResult.ShouldNotBeNull(); |
| 178 | + compareResult.UnchangedItems.ShouldNotBeEmpty("All channels should be unchanged."); |
| 179 | + compareResult.ChangedItems.ShouldBeEmpty("No channels should be changed."); |
| 180 | + compareResult.ItemsOnlyInLeft.ShouldBeEmpty("No channels should exist only in the test data."); |
| 181 | + compareResult.ItemsOnlyInRight.ShouldBeEmpty("No channels should exist only in the loaded project."); |
| 182 | + |
| 183 | + foreach (var (ExpectedChannel, LoadedChannel) in testProject?.Project?.Channels?.Zip(project?.Channels ?? []) ?? []) |
| 184 | + { |
| 185 | + var deviceCompareResult = EntityCompare.Compare<DeviceCollection, Device>(ExpectedChannel.Devices, LoadedChannel.Devices); |
| 186 | + deviceCompareResult.ShouldNotBeNull(); |
| 187 | + deviceCompareResult.UnchangedItems.ShouldNotBeEmpty($"All devices in channel {ExpectedChannel.Name} should be unchanged."); |
| 188 | + deviceCompareResult.ChangedItems.ShouldBeEmpty($"No devices in channel {ExpectedChannel.Name} should be changed."); |
| 189 | + deviceCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No devices should exist only in the test data for channel {ExpectedChannel.Name}."); |
| 190 | + deviceCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No devices should exist only in the loaded project for channel {ExpectedChannel.Name}."); |
| 191 | + |
| 192 | + foreach (var (ExpectedDevice, LoadedDevice) in ExpectedChannel.Devices?.Zip(LoadedChannel.Devices ?? []) ?? []) |
| 193 | + { |
| 194 | + if (ExpectedDevice.Tags?.Count > 0 || LoadedDevice.Tags?.Count > 0) |
| 195 | + { |
| 196 | + var tagCompareResult = EntityCompare.Compare<DeviceTagCollection, Tag>(ExpectedDevice.Tags, LoadedDevice.Tags); |
| 197 | + tagCompareResult.ShouldNotBeNull(); |
| 198 | + tagCompareResult.UnchangedItems.ShouldNotBeEmpty($"All tags in device {ExpectedDevice.Name} should be unchanged."); |
| 199 | + tagCompareResult.ChangedItems.ShouldBeEmpty($"No tags in device {ExpectedDevice.Name} should be changed."); |
| 200 | + tagCompareResult.ItemsOnlyInLeft.ShouldBeEmpty($"No tags should exist only in the test data for device {ExpectedDevice.Name}."); |
| 201 | + tagCompareResult.ItemsOnlyInRight.ShouldBeEmpty($"No tags should exist only in the loaded project for device {ExpectedDevice.Name}."); |
| 202 | + } |
| 203 | + |
| 204 | + CompareTagGroupsRecursive(ExpectedDevice.TagGroups, LoadedDevice.TagGroups, ExpectedDevice.Name); |
| 205 | + } |
| 206 | + } |
| 207 | + } |
| 208 | + |
143 | 209 | private static void CompareTagGroupsRecursive(DeviceTagGroupCollection? expected, DeviceTagGroupCollection? actual, string parentName) |
144 | 210 | { |
145 | 211 | if ((expected?.Count ?? 0) == 0 && (actual?.Count ?? 0) == 0) |
|
0 commit comments