Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ public async Task AutomaticTagGenerationAsync_ShouldReturnKepServerJobPromise_Wh

// Act
var result = await _kepwareApiClient.ApiServices.AutomaticTagGenerationAsync(UNIT_TEST_CHANNEL, UNIT_TEST_DEVICE, TimeSpan.FromSeconds(30));
var jobResult = await result.AwaitCompletionAsync();

// Assert
result.ShouldNotBeNull();
result.Endpoint.ShouldBe(ENDPOINT_TAG_GENERATION);
result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30));
jobResult.Value.ShouldBeFalse();
jobResult.IsSuccess.ShouldBeFalse();
jobResult.ResponseCode.ShouldBe(ApiResponseCode.BadRequest);
}

[Fact]
Expand Down Expand Up @@ -113,6 +117,7 @@ public async Task AutomaticTagGenerationAsync_ShouldReturnSuccess_WhenJobComplet
// Assert
completionResult.Value.ShouldBeTrue();
completionResult.IsSuccess.ShouldBeTrue();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Success);
}

[Fact]
Expand All @@ -135,6 +140,7 @@ public async Task AutomaticTagGenerationAsync_ShouldReturnSuccess_WhenJobComplet
// Assert
completionResult.Value.ShouldBeTrue();
completionResult.IsSuccess.ShouldBeTrue();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Success);
}

[Fact]
Expand All @@ -155,6 +161,7 @@ public async Task AutomaticTagGenerationAsync_ShouldReturnFailure_WhenJobFailsAf
// Assert
completionResult.Value.ShouldBeFalse();
completionResult.IsSuccess.ShouldBeFalse();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Timeout);
}

[Fact]
Expand All @@ -180,6 +187,8 @@ public async Task AutomaticTagGenerationAsync_ShouldReturnFailure_WhenJobFailsAf
// Assert
completionResult.Value.ShouldBeFalse();
completionResult.IsSuccess.ShouldBeFalse();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.ServiceUnavailable);
completionResult.Message.ShouldBe(jobStatusFailed.Message);
}
}
}
12 changes: 8 additions & 4 deletions Kepware.Api.Test/ApiClient/GetProductInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ public async Task GetProductInfoAsync_ShouldReturnProductInfo_WhenApiRespondsSuc

#region GetProductInfoAsync - SupportsJsonProjectLoadService

//TODO: Add more test cases for TKS versions as well. Different product name
[Theory]
[InlineData("KEPServerEX", "12", 6, 17, true)] // Supports JSON Project Load Service (6.17+)
[InlineData("KEPServerEX", "12", 6, 16, false)] // Does not support it (6.16)
[InlineData("ThingWorxKepwareEdge", "13", 1, 10, true)] // Supports it (1.10+)
[InlineData("ThingworxKepwareServer", "12", 6, 17, true)] // Supports JSON Project Load Service (6.17+)
[InlineData("ThingworxKepwareServer", "12", 6, 16, false)] // Does not support it (6.16)
[InlineData("ThingWorxKepwareEdge", "13", 1, 10, true)] // Supports JSON Project Load Service (1.10+)
[InlineData("ThingWorxKepwareEdge", "13", 1, 9, false)] // Does not support it (1.9)
[InlineData("Kepware Edge", "13", 1, 0, true)] // Supports JSON Project Load Service
[InlineData("UnknownProduct", "99", 10, 0, false)] // Unknown product, should be false
public async Task GetProductInfoAsync_ShouldReturnCorrect_SupportsJsonProjectLoadService(
string productName, string productId, int majorVersion, int minorVersion, bool expectedResult)
Expand All @@ -62,8 +64,10 @@ public async Task GetProductInfoAsync_ShouldReturnCorrect_SupportsJsonProjectLoa
#region GetProductInfoAsync - ProductType

[Theory]
[InlineData("KEPServerEX", "12", ProductType.KEPServerEX)]
[InlineData("ThingWorxKepwareEdge", "13", ProductType.ThingWorxKepwareEdge)]
[InlineData("KEPServerEX", "12", ProductType.KepwareServer)]
[InlineData("ThingworxKepwareServer", "12", ProductType.KepwareServer)]
[InlineData("ThingWorxKepwareEdge", "13", ProductType.KepwareEdge)]
[InlineData("Kepware Edge", "13", ProductType.KepwareEdge)]
[InlineData("UnknownProduct", "99", ProductType.Unknown)]
[InlineData("InvalidProduct", "abc", ProductType.Unknown)] // Invalid ID, should be Unknown
public async Task GetProductInfoAsync_ShouldReturnCorrect_ProductType(
Expand Down
99 changes: 98 additions & 1 deletion Kepware.Api.Test/ApiClient/ProjectApiHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,49 @@ public async Task GetOrCreateChannelAsync_ShouldCreateChannel_WhenChannelDoesNot
Assert.Equal(channelName, result.Name);
}

[Fact]
public async Task GetChannelAsync_ShouldReturnChannel_WhenChannelExists()
{
// Arrange
var channelName = "ExistingChannel";
var channelJson = """
{
"PROJECT_ID": 676550906,
"common.ALLTYPES_NAME": "ExistingChannel",
"common.ALLTYPES_DESCRIPTION": "Example Channel",
"servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Simulator"
}
""";

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channelName}")
.ReturnsResponse(channelJson, "application/json");

// Act
var result = await _projectApiHandler.Channels.GetChannelAsync(channelName);

// Assert
Assert.NotNull(result);
Assert.Equal(channelName, result.Name);
}

[Fact]
public async Task GetChannelAsync_ShouldReturnNull_WhenChannelDoesNotExist()
{
// Arrange
await ConfigureToServeDrivers();

var channelName = "NewChannel";

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channelName}")
.ReturnsResponse(HttpStatusCode.NotFound);

// Act
var result = await _projectApiHandler.Channels.GetChannelAsync(channelName);

// Assert
Assert.Null(result);
}

[Fact]
public async Task UpdateChannelAsync_ShouldReturnTrue_WhenUpdateIsSuccessful()
{
Expand Down Expand Up @@ -190,6 +233,57 @@ public async Task GetOrCreateDeviceAsync_ShouldCreateDevice_WhenDeviceDoesNotExi
Assert.Equal(deviceName, result.Name);
}

[Fact]
public async Task GetDeviceAsync_ShouldReturnDevice_WhenDeviceExists()
{
// Arrange
await ConfigureToServeDrivers();
var channel = new Channel { Name = "ExistingChannel" };
var deviceName = "ExistingDevice";
var deviceJson = """
{
"PROJECT_ID": 676550906,
"common.ALLTYPES_NAME": "ExistingDevice",
"common.ALLTYPES_DESCRIPTION": "Example Device",
"servermain.DEVICE_CHANNEL_ASSIGNMENT": "ExistingChannel"
}
""";

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices/{deviceName}")
.ReturnsResponse(deviceJson, "application/json");

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices/{deviceName}/tags")
.ReturnsResponse("[]", "application/json");

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices/{deviceName}/tag_groups")
.ReturnsResponse("[]", "application/json");

// Act
var result = await _projectApiHandler.Devices.GetDeviceAsync(channel, deviceName);

// Assert
Assert.NotNull(result);
Assert.Equal(deviceName, result.Name);
}

[Fact]
public async Task GetDeviceAsync_ShouldReturnNull_WhenDeviceDoesNotExist()
{
// Arrange
await ConfigureToServeDrivers();
var channel = new Channel { Name = "ExistingChannel", DeviceDriver = "Simulator" };
var deviceName = "NewDevice";

_httpMessageHandlerMock.SetupRequest(HttpMethod.Get, TEST_ENDPOINT + $"/config/v1/project/channels/{channel.Name}/devices/{deviceName}")
.ReturnsResponse(HttpStatusCode.NotFound);

// Act
var result = await _projectApiHandler.Devices.GetDeviceAsync(channel, deviceName);

// Assert
Assert.Null(result);
}

[Fact]
public async Task UpdateDeviceAsync_ShouldReturnTrue_WhenUpdateIsSuccessful()
{
Expand Down Expand Up @@ -269,7 +363,8 @@ public async Task LoadTagGroupsRecursiveAsync_ShouldLoadTagGroupsCorrectly()
.ReturnsResponse("[]", "application/json");

var tagGroup = new DeviceTagGroup { Name = "TagGroup1", Owner = device };
var tagGroups = new List<DeviceTagGroup> { tagGroup };
var tagGroup2 = new DeviceTagGroup { Name = "TagGroup1", Owner = tagGroup };
var tagGroups = new List<DeviceTagGroup> { tagGroup , tagGroup2 };

// Act
await ProjectApiHandler.LoadTagGroupsRecursiveAsync(_kepwareApiClient, tagGroups);
Expand All @@ -278,6 +373,8 @@ public async Task LoadTagGroupsRecursiveAsync_ShouldLoadTagGroupsCorrectly()
Assert.NotNull(tagGroup.TagGroups);
Assert.Single(tagGroup.TagGroups);
Assert.Equal("TagGroup1", tagGroup.TagGroups.First().Name);
Assert.NotNull(tagGroup2.TagGroups);
Assert.Empty(tagGroup2.TagGroups);
}

#endregion
Expand Down
13 changes: 12 additions & 1 deletion Kepware.Api.Test/ApiClient/ReinitializeRuntimeAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ public async Task ReinitializeRuntimeAsync_ShouldReturnKepServerJobPromise_WhenA

// Act
var result = await _kepwareApiClient.ApiServices.ReinitializeRuntimeAsync(TimeSpan.FromSeconds(30));

var jobResult = await result.AwaitCompletionAsync();

// Assert
result.ShouldNotBeNull();
result.Endpoint.ShouldBe("/config/v1/project/services/ReinitializeRuntime");
result.JobTimeToLive.ShouldBe(TimeSpan.FromSeconds(30));
jobResult.Value.ShouldBeFalse();
jobResult.IsSuccess.ShouldBeFalse();
jobResult.ResponseCode.ShouldBe(ApiResponseCode.BadRequest);

}

[Fact]
Expand Down Expand Up @@ -111,6 +116,7 @@ public async Task ReinitializeRuntimeAsync_ShouldReturnSuccess_WhenJobCompletesS
// Assert
completionResult.Value.ShouldBeTrue();
completionResult.IsSuccess.ShouldBeTrue();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Success);
}

[Fact]
Expand All @@ -133,6 +139,7 @@ public async Task ReinitializeRuntimeAsync_ShouldReturnSuccess_WhenJobCompletesS
// Assert
completionResult.Value.ShouldBeTrue();
completionResult.IsSuccess.ShouldBeTrue();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Success);
}

[Fact]
Expand All @@ -153,6 +160,8 @@ public async Task ReinitializeRuntimeAsync_ShouldReturnFailure_WhenJobFailsAfter
// Assert
completionResult.Value.ShouldBeFalse();
completionResult.IsSuccess.ShouldBeFalse();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.Timeout);

}

[Fact]
Expand All @@ -178,6 +187,8 @@ public async Task ReinitializeRuntimeAsync_ShouldReturnFailure_WhenJobFailsAfter
// Assert
completionResult.Value.ShouldBeFalse();
completionResult.IsSuccess.ShouldBeFalse();
completionResult.ResponseCode.ShouldBe(ApiResponseCode.ServiceUnavailable);
completionResult.Message.ShouldBe(jobStatusFailed.Message);
}
}
}
70 changes: 69 additions & 1 deletion Kepware.Api.TestIntg/ApiClient/ProjectApiHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,24 @@ public async Task GetOrCreateChannelAsync_ShouldCreateChannel_WhenChannelDoesNot
var channel = CreateTestChannel();

// Act
var result = await _projectApiHandler.Channels.GetOrCreateChannelAsync(channel.Name, channel.DeviceDriver);
var result = await _projectApiHandler.Channels.GetOrCreateChannelAsync(channel.Name, channel.DeviceDriver!);

// Assert
Assert.NotNull(result);
Assert.Equal(channel.Name, result.Name);

// Clean up
await DeleteAllChannelsAsync();
}

[Fact]
public async Task GetChannelAsync_ShouldReturnChannel_WhenChannelExists()
{
// Arrange
var channel = await AddTestChannel();

// Act
var result = await _projectApiHandler.Channels.GetChannelAsync(channel.Name);

// Assert
Assert.NotNull(result);
Expand All @@ -57,6 +74,22 @@ public async Task GetOrCreateChannelAsync_ShouldCreateChannel_WhenChannelDoesNot
await DeleteAllChannelsAsync();
}

[Fact]
public async Task GetChannelAsync_ShouldReturnNull_WhenChannelDoesNotExist()
{
// Arrange
var channel = CreateTestChannel();

// Act
var result = await _projectApiHandler.Channels.GetChannelAsync(channel.Name);

// Assert
Assert.Null(result);

// Clean up
await DeleteAllChannelsAsync();
}

[Fact]
public async Task UpdateChannelAsync_ShouldReturnTrue_WhenUpdateIsSuccessful()
{
Expand Down Expand Up @@ -130,6 +163,41 @@ public async Task GetOrCreateDeviceAsync_ShouldCreateDevice_WhenDeviceDoesNotExi
await DeleteAllChannelsAsync();
}

[Fact]
public async Task GetDeviceAsync_ShouldReturnDevice_WhenDeviceExists()
{
// Arrange
var channel = await AddTestChannel();
var device = await AddTestDevice(channel);

// Act
var result = await _projectApiHandler.Devices.GetDeviceAsync(channel, device.Name);

// Assert
Assert.NotNull(result);
Assert.Equal(device.Name, result.Name);

// Clean up
await DeleteAllChannelsAsync();
}

[Fact]
public async Task GetDeviceAsync_ShouldReturnNull_WhenDeviceDoesNotExist()
{
// Arrange
var channel = await AddTestChannel();
var device = CreateTestDevice(channel);

// Act
var result = await _projectApiHandler.Devices.GetDeviceAsync(channel, device.Name);

// Assert
Assert.Null(result);

// Clean up
await DeleteAllChannelsAsync();
}

[Fact]
public async Task UpdateDeviceAsync_ShouldReturnTrue_WhenUpdateIsSuccessful()
{
Expand Down
2 changes: 1 addition & 1 deletion Kepware.Api.TestIntg/ApiClient/UpdateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task Update_MultipleItems_ShouldUpdateAll()
var results = await _kepwareApiClient.GenericConfig.UpdateItemsAsync<DeviceTagCollection, Tag>(tags, device);

// Assert
results.Count.ShouldBe(tags.Count);
results.Length.ShouldBe(tags.Count);
results.ShouldAllBe(r => r == true);

// Clean up
Expand Down
4 changes: 2 additions & 2 deletions Kepware.Api.TestIntg/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"TestServer": {
"Host": "http://localhost",
"Port": 57412,
"UserName": "Administrator",
"Password": "ReallyStrongPassword400!"
"UserName": "Test",
"Password": "Kepware400400400"
}
}
}
Loading
Loading