Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended search query and added tests #5

Merged
merged 1 commit into from
Jul 10, 2024
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
8 changes: 7 additions & 1 deletion src/Kwtc.Tjek.Client.Abstractions/IClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ namespace Kwtc.Tjek.Client.Abstractions;

public interface IClient
{
Task<IReadOnlyList<Offer>> Search(string query, CancellationToken cancellationToken = default);
public Task<IReadOnlyList<Offer>> Search(
string query,
string? dealerId = null,
string? catalogId = null,
string? publicationType = null,
int? limit = null,
CancellationToken cancellationToken = default);
}
5 changes: 4 additions & 1 deletion src/Kwtc.Tjek.Client.Abstractions/Models/Si.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace Kwtc.Tjek.Client.Abstractions.Models;

/// <summary>
/// System of units
/// </summary>
public class Si
{
public long Factor { get; set; }

public long To { get; set; }
public long Symbol { get; set; }
}
42 changes: 38 additions & 4 deletions src/Kwtc.Tjek.Client/Client.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Text;
using System.Text.Json;
using CommunityToolkit.Diagnostics;
using Kwtc.Tjek.Client.Abstractions;
using Kwtc.Tjek.Client.Abstractions.Models;
Expand All @@ -14,12 +15,30 @@ public Client(IHttpClientFactory httpClientFactory)
this.httpClientFactory = httpClientFactory;
}

public async Task<IReadOnlyList<Offer>> Search(string query, CancellationToken cancellationToken = default)
public async Task<IReadOnlyList<Offer>> Search(
string query,
string? dealerId = null,
string? catalogId = null,
string? publicationType = null,
int? limit = null,
CancellationToken cancellationToken = default)
{
Guard.IsNotNullOrEmpty(query, nameof(query));


// Build query string
var builder = new StringBuilder();
builder.Append($"?query={query.ToValidUri()}");

var queryString = BuildQueryString(new Dictionary<string, string>
{
{ "dealer_id", $"{dealerId}" },
{ "catalog_id", $"{catalogId}" },
{ "types", $"{publicationType}" },
{ "limit", $"{limit}" },
}, builder);

var client = this.httpClientFactory.CreateClient(Constants.HttpClientName);
var response = await client.GetAsync($"v2/offers/search?query={query.ToValidUri()}", cancellationToken);
var response = await client.GetAsync($"v2/offers/search{queryString}", cancellationToken);

response.EnsureSuccessStatusCode();

Expand All @@ -33,4 +52,19 @@ public async Task<IReadOnlyList<Offer>> Search(string query, CancellationToken c

return result ?? [];
}

private static string BuildQueryString(IDictionary<string, string> parameters, StringBuilder builder)
{
foreach (var parameter in parameters)
{
if (string.IsNullOrEmpty(parameter.Value))
{
continue;
}

builder.Append($"&{parameter.Key}={parameter.Value.ToValidUri()}");
}

return builder.ToString();
}
}
2 changes: 1 addition & 1 deletion src/Kwtc.Tjek.Client/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public static class StringExtensions
public static string ToValidUri(this string input)
{
var str = input;
str = System.Text.RegularExpressions.Regex.Replace(str, @"[^a-zA-Z0-9\s-æøåÆØÅ]", "");
str = System.Text.RegularExpressions.Regex.Replace(str, @"[^a-zA-Z0-9\s-æøåÆØÅ?&=]", "");
str = System.Text.RegularExpressions.Regex.Replace(str, @"\s+", " ").Trim();

return Uri.EscapeDataString(str);
Expand Down
134 changes: 133 additions & 1 deletion test/Kwtc.Tjek.Client.Tests/UnitTests/ClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,138 @@ public async Task Search_ValidSearchTermUnexpectedResponseContent_ShouldThrow()
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndDealerIdExpectedResponse_ShouldSendRequest()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&dealer_id=123",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, dealerId: "123");

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndDealerIdLimitExpectedResponse_ShouldSendRequest()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&dealer_id=123&limit=10",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, dealerId: "123", limit: 10);

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndDealerIdNullExpectedResponse_RequestShouldNotContainDealerId()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&limit=10",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, dealerId: null, limit: 10);

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndCatalogIdExpectedResponse_ShouldSendRequest()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&catalog_id=123",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, catalogId: "123");

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndPublicationTypeExpectedResponse_ShouldSendRequest()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&types=123",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, publicationType: "123");

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

[Fact]
public async Task Search_ValidSearchTermAndLimitExpectedResponse_ShouldSendRequest()
{
// Arrange
const string searchTerm = "ValidSearchTerm";
var httpClient = GetMockedClient(
uri: $"search?query={searchTerm.ToValidUri()}&limit=10",
content: JsonSerializer.Serialize(new List<Offer> { new() })
);
var sut = GetSut();

this.httpClientFactoryMock
.Setup(x => x.CreateClient(Constants.HttpClientName))
.Returns(httpClient);

// Act
await sut.Search(query: searchTerm, limit: 10);

// Assert
this.httpClientFactoryMock.Verify(x => x.CreateClient(Constants.HttpClientName), Times.Once);
}

private static HttpClient GetMockedClient(string uri, HttpStatusCode statusCode = HttpStatusCode.OK, string content = "")
{
var httpMessageHandlerMock = new Mock<HttpMessageHandler>();
Expand All @@ -116,7 +248,7 @@ private static HttpClient GetMockedClient(string uri, HttpStatusCode statusCode
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.Is<HttpRequestMessage>(x =>
x.RequestUri!.AbsoluteUri.EndsWith(uri)
x.RequestUri!.AbsoluteUri.Contains(uri)
),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
Expand Down
Loading