Introduced a new test class `RecActionApiTests` to validate the behavior of the `RecActions` API client. - Added tests for `GetAsync`, `CreateAsync`, `UpdateAsync`, `DeleteAsync`, and `InvokeAsync` methods to ensure proper handling of valid and invalid inputs. - Verified dependency injection resolution for `RecClient` and `RecActions`. - Included assertions for HTTP status codes, request methods, and query parameters. - Handled edge cases such as missing test data with `Assert.Pass` or `Assert.Ignore`. - Utilized scoped clients for test isolation and resource management. These changes improve test coverage and ensure the reliability of the `RecActions` API client.
160 lines
5.1 KiB
C#
160 lines
5.1 KiB
C#
using System.Net;
|
|
using Microsoft.Extensions.Configuration;
|
|
using ReC.Application.Common.Dto;
|
|
using ReC.Application.Common.Procedures.UpdateProcedure.Dto;
|
|
using ReC.Application.RecActions.Commands;
|
|
using ReC.Client;
|
|
using ReC.Client.Api;
|
|
using ClientInvokeReferences = ReC.Client.Api.InvokeReferences;
|
|
|
|
namespace ReC.Tests.Client;
|
|
|
|
[TestFixture]
|
|
public class RecActionApiTests : RecClientTestBase
|
|
{
|
|
[Test]
|
|
public void ReCClient_is_resolvable_through_dependency_injection()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
Assert.That(client, Is.Not.Null);
|
|
Assert.That(client.RecActions, Is.Not.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetAsync_without_filters_returns_deserialized_result_or_throws_not_found()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
try
|
|
{
|
|
var actions = await client.RecActions.GetAsync<RecActionViewDto[]>();
|
|
Assert.That(actions, Is.Not.Null);
|
|
}
|
|
catch (ReCApiException ex)
|
|
{
|
|
Assert.That(ex.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
|
|
Assert.That(ex.Method, Is.EqualTo("GET"));
|
|
Assert.That(ex.RequestUri!.AbsolutePath, Does.EndWith("api/RecAction"));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetAsync_with_profile_filter_returns_only_matching_actions()
|
|
{
|
|
var profileId = Configuration.GetValue<long?>("FakeProfileId");
|
|
if (profileId is null or <= 0)
|
|
Assert.Ignore("FakeProfileId must be configured in appsettings.json for this test.");
|
|
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
RecActionViewDto[]? actions;
|
|
try
|
|
{
|
|
actions = await client.RecActions.GetAsync<RecActionViewDto[]>(profileId: profileId);
|
|
}
|
|
catch (ReCApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
|
|
{
|
|
Assert.Pass("NotFound is acceptable when test data is unavailable.");
|
|
return;
|
|
}
|
|
|
|
Assert.That(actions, Is.Not.Null.And.Not.Empty);
|
|
Assert.That(actions, Has.All.Matches<RecActionViewDto>(a => a.ProfileId == profileId));
|
|
}
|
|
|
|
[Test]
|
|
public void GetAsync_with_unknown_profile_throws_not_found()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
var ex = Assert.ThrowsAsync<ReCApiException>(async () =>
|
|
await client.RecActions.GetAsync<RecActionViewDto[]>(profileId: long.MaxValue));
|
|
|
|
Assert.That(ex, Is.Not.Null);
|
|
Assert.That(ex!.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
|
|
Assert.That(ex.Method, Is.EqualTo("GET"));
|
|
Assert.That(ex.RequestUri!.Query, Does.Contain("ProfileId="));
|
|
}
|
|
|
|
[Test]
|
|
public void CreateAsync_with_invalid_foreign_key_throws_ReCApiException()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
var payload = new InsertActionCommand
|
|
{
|
|
ProfileId = long.MaxValue,
|
|
EndpointId = long.MaxValue,
|
|
Active = true,
|
|
Sequence = 1
|
|
};
|
|
|
|
var ex = Assert.ThrowsAsync<ReCApiException>(async () => await client.RecActions.CreateAsync(payload));
|
|
Assert.That(ex, Is.Not.Null);
|
|
Assert.That((int)ex!.StatusCode, Is.GreaterThanOrEqualTo(400));
|
|
Assert.That(ex.Method, Is.EqualTo("POST"));
|
|
}
|
|
|
|
[Test]
|
|
public void UpdateAsync_with_unknown_id_throws_ReCApiException_with_method_PUT()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
var unknownId = long.MaxValue;
|
|
var payload = new UpdateActionDto
|
|
{
|
|
ProfileId = 1,
|
|
Active = false,
|
|
Sequence = 1
|
|
};
|
|
|
|
var ex = Assert.ThrowsAsync<ReCApiException>(async () => await client.RecActions.UpdateAsync(unknownId, payload));
|
|
Assert.That(ex, Is.Not.Null);
|
|
Assert.That(ex!.Method, Is.EqualTo("PUT"));
|
|
}
|
|
|
|
[Test]
|
|
public void DeleteAsync_sends_payload_as_query_string_not_body()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
var payload = new DeleteActionCommand
|
|
{
|
|
Start = long.MaxValue - 1,
|
|
End = long.MaxValue,
|
|
Force = false
|
|
};
|
|
|
|
try
|
|
{
|
|
client.RecActions.DeleteAsync(payload).GetAwaiter().GetResult();
|
|
}
|
|
catch (ReCApiException ex)
|
|
{
|
|
Assert.That(ex.Method, Is.EqualTo("DELETE"));
|
|
Assert.That(ex.RequestUri!.Query, Does.Contain("Start=").And.Contains("End=").And.Contains("Force="));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void InvokeAsync_with_unknown_profile_throws_ReCApiException()
|
|
{
|
|
var (client, scope) = CreateScopedClient();
|
|
using var _ = scope;
|
|
|
|
var ex = Assert.ThrowsAsync<ReCApiException>(async () =>
|
|
await client.RecActions.InvokeAsync(long.MaxValue, new ClientInvokeReferences { BatchId = "test-batch" }));
|
|
|
|
Assert.That(ex, Is.Not.Null);
|
|
Assert.That(ex!.Method, Is.EqualTo("POST"));
|
|
}
|
|
}
|