test: add LookupApiClientTests with route and encoding tests
- Route verification tests for all 4 methods (FindItems, FindProfitCenters, FindWorkCenters, FindOperators) - Query string encoding tests verifying special characters (&, =) and spaces are properly URL-encoded - Success tests for all lookup methods verifying deserialization - Representative error test for 500 status code
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using JdeScoping.Client.Services;
|
||||
using JdeScoping.Core.ApiContracts;
|
||||
using JdeScoping.Core.ViewModels;
|
||||
using RichardSzalay.MockHttp;
|
||||
using Shouldly;
|
||||
|
||||
namespace JdeScoping.Client.Tests.Services;
|
||||
|
||||
public class LookupApiClientTests
|
||||
{
|
||||
private readonly MockHttpMessageHandler _mockHttp;
|
||||
private readonly LookupApiClient _client;
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
public LookupApiClientTests()
|
||||
{
|
||||
_mockHttp = new MockHttpMessageHandler();
|
||||
var httpClient = new HttpClient(_mockHttp) { BaseAddress = new Uri("http://localhost/") };
|
||||
_client = new LookupApiClient(httpClient);
|
||||
}
|
||||
|
||||
// Route verification tests
|
||||
|
||||
[Fact]
|
||||
public async Task FindItemsAsync_CallsCorrectRoute_WithQuery()
|
||||
{
|
||||
// Arrange
|
||||
var query = "TEST123";
|
||||
var expectedUrl = $"http://localhost/{ApiRoutes.Lookup.FindItems(query)}";
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, expectedUrl)
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindItemsAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindProfitCentersAsync_CallsCorrectRoute()
|
||||
{
|
||||
// Arrange
|
||||
var query = "PC1";
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, $"http://localhost/{ApiRoutes.Lookup.FindProfitCenters(query)}")
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindProfitCentersAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindWorkCentersAsync_CallsCorrectRoute()
|
||||
{
|
||||
// Arrange
|
||||
var query = "WC1";
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, $"http://localhost/{ApiRoutes.Lookup.FindWorkCenters(query)}")
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindWorkCentersAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindOperatorsAsync_CallsCorrectRoute()
|
||||
{
|
||||
// Arrange
|
||||
var query = "John";
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, $"http://localhost/{ApiRoutes.Lookup.FindOperators(query)}")
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindOperatorsAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
// Query string encoding tests
|
||||
|
||||
[Fact]
|
||||
public async Task FindItemsAsync_EncodesSpecialCharacters_InQueryString()
|
||||
{
|
||||
// Arrange - query with special characters that need URL encoding
|
||||
var query = "TEST&ITEM=1";
|
||||
var expectedUrl = $"http://localhost/{ApiRoutes.Lookup.FindItems(query)}";
|
||||
// The URL should have encoded & as %26 and = as %3D
|
||||
expectedUrl.ShouldContain("%26");
|
||||
expectedUrl.ShouldContain("%3D");
|
||||
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, expectedUrl)
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindItemsAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindItemsAsync_EncodesSpaces_InQueryString()
|
||||
{
|
||||
// Arrange - query with spaces
|
||||
var query = "TEST ITEM";
|
||||
var expectedUrl = $"http://localhost/{ApiRoutes.Lookup.FindItems(query)}";
|
||||
// The URL should have encoded space as %20
|
||||
expectedUrl.ShouldContain("%20");
|
||||
|
||||
var request = _mockHttp.Expect(HttpMethod.Get, expectedUrl)
|
||||
.Respond("application/json", "[]");
|
||||
|
||||
// Act
|
||||
await _client.FindItemsAsync(query);
|
||||
|
||||
// Assert
|
||||
_mockHttp.GetMatchCount(request).ShouldBe(1);
|
||||
}
|
||||
|
||||
// Success tests
|
||||
|
||||
[Fact]
|
||||
public async Task FindItemsAsync_Success_ReturnsItemList()
|
||||
{
|
||||
// Arrange
|
||||
var items = new List<ItemViewModel>
|
||||
{
|
||||
new() { ItemNumber = "ITEM1", Description = "Item One" },
|
||||
new() { ItemNumber = "ITEM2", Description = "Item Two" }
|
||||
};
|
||||
_mockHttp.When(HttpMethod.Get, "*")
|
||||
.Respond("application/json", JsonSerializer.Serialize(items, JsonOptions));
|
||||
|
||||
// Act
|
||||
var result = await _client.FindItemsAsync("ITEM");
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Value.Count.ShouldBe(2);
|
||||
result.Value[0].ItemNumber.ShouldBe("ITEM1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindOperatorsAsync_Success_ReturnsUserList()
|
||||
{
|
||||
// Arrange
|
||||
var users = new List<JdeUserViewModel>
|
||||
{
|
||||
new() { UserId = "USER1", FullName = "John Doe" }
|
||||
};
|
||||
_mockHttp.When(HttpMethod.Get, "*")
|
||||
.Respond("application/json", JsonSerializer.Serialize(users, JsonOptions));
|
||||
|
||||
// Act
|
||||
var result = await _client.FindOperatorsAsync("John");
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Value.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindProfitCentersAsync_Success_ReturnsProfitCenterList()
|
||||
{
|
||||
// Arrange
|
||||
var profitCenters = new List<ProfitCenterViewModel>
|
||||
{
|
||||
new() { Code = "PC001", Description = "Profit Center One" },
|
||||
new() { Code = "PC002", Description = "Profit Center Two" }
|
||||
};
|
||||
_mockHttp.When(HttpMethod.Get, "*")
|
||||
.Respond("application/json", JsonSerializer.Serialize(profitCenters, JsonOptions));
|
||||
|
||||
// Act
|
||||
var result = await _client.FindProfitCentersAsync("PC");
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Value.Count.ShouldBe(2);
|
||||
result.Value[0].Code.ShouldBe("PC001");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindWorkCentersAsync_Success_ReturnsWorkCenterList()
|
||||
{
|
||||
// Arrange
|
||||
var workCenters = new List<WorkCenterViewModel>
|
||||
{
|
||||
new() { Code = "WC001", Description = "Work Center One" }
|
||||
};
|
||||
_mockHttp.When(HttpMethod.Get, "*")
|
||||
.Respond("application/json", JsonSerializer.Serialize(workCenters, JsonOptions));
|
||||
|
||||
// Act
|
||||
var result = await _client.FindWorkCentersAsync("WC");
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Value.Count.ShouldBe(1);
|
||||
result.Value[0].Code.ShouldBe("WC001");
|
||||
}
|
||||
|
||||
// Representative error test
|
||||
|
||||
[Fact]
|
||||
public async Task FindItemsAsync_500_ReturnsError()
|
||||
{
|
||||
// Arrange
|
||||
_mockHttp.When(HttpMethod.Get, "*")
|
||||
.Respond(HttpStatusCode.InternalServerError, "text/plain", "Internal Server Error");
|
||||
|
||||
// Act
|
||||
var result = await _client.FindItemsAsync("test");
|
||||
|
||||
// Assert
|
||||
result.IsError.ShouldBeTrue();
|
||||
result.Error.StatusCode.ShouldBe(500);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user