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

CDMS-200 adding decision integration tests & refactoring ApplicationF… #30

Merged
merged 4 commits into from
Dec 27, 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
15 changes: 6 additions & 9 deletions Btms.Backend.IntegrationTests/AnalyticsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
namespace Btms.Backend.IntegrationTests;

[Trait("Category", "Integration")]
public class AnalyticsTests(IntegrationTestsApplicationFactory factory, ITestOutputHelper testOutputHelper)
: BaseApiTests(factory, testOutputHelper), IClassFixture<IntegrationTestsApplicationFactory>
public class AnalyticsTests(ApplicationFactory factory, ITestOutputHelper testOutputHelper)
: BaseApiTests(factory, testOutputHelper), IClassFixture<ApplicationFactory>
{

// private static void ShouldNotBeNull<T>([DoesNotReturnIf(true), NotNull] T? value)
Expand All @@ -33,8 +33,7 @@ public class AnalyticsTests(IntegrationTestsApplicationFactory factory, ITestOut
public async Task GetIndividualMultiSeriesDatetimeChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=importNotificationLinkingByCreated");
var response = await Client.GetAnalyticsDashboard("importNotificationLinkingByCreated");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());
Expand All @@ -51,8 +50,7 @@ public async Task GetIndividualMultiSeriesDatetimeChart()
public async Task GetIndividualMultiSeriesChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=lastMonthMovementsByItemCount");
var response = await Client.GetAnalyticsDashboard("lastMonthMovementsByItemCount");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());
Expand All @@ -69,8 +67,7 @@ public async Task GetIndividualMultiSeriesChart()
public async Task GetIndividualSingleSeriesChart()
{
//Act
var response = await Client.GetAsync(
"/analytics/dashboard?chartsToRender=last7DaysImportNotificationsLinkingStatus");
var response = await Client.GetAnalyticsDashboard("last7DaysImportNotificationsLinkingStatus");

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());
Expand All @@ -87,7 +84,7 @@ public async Task GetIndividualSingleSeriesChart()
public async Task GetAllCharts()
{
//Act
var response = await Client.GetAsync("/analytics/dashboard");
var response = await Client.GetAnalyticsDashboard();

// Assert
response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString());
Expand Down
91 changes: 12 additions & 79 deletions Btms.Backend.IntegrationTests/BaseApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,89 +18,22 @@ namespace Btms.Backend.IntegrationTests;

public abstract class BaseApiTests
{
protected readonly HttpClient Client;
protected readonly IntegrationTestsApplicationFactory Factory;

protected BaseApiTests(IntegrationTestsApplicationFactory factory, ITestOutputHelper testOutputHelper)
protected readonly BtmsClient Client;
internal readonly IIntegrationTestsApplicationFactory Factory;
// protected readonly IntegrationTestsApplicationFactory Factory;

protected async Task ClearDb()
{
await Client.ClearDb();
}
protected BaseApiTests(IIntegrationTestsApplicationFactory factory, ITestOutputHelper testOutputHelper, string databaseName = "SmokeTests")
{
Factory = factory;
Factory.TestOutputHelper = testOutputHelper;
Factory.DatabaseName = "SmokeTests";
Factory.DatabaseName = databaseName;
Client =
Factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });
var credentials = "IntTest:Password";
var credentialsAsBytes = Encoding.UTF8.GetBytes(credentials.ToCharArray());
var encodedCredentials = Convert.ToBase64String(credentialsAsBytes);
Client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(BasicAuthenticationDefaults.AuthenticationScheme, encodedCredentials);
}

private async Task WaitOnJobCompleting(Uri jobUri)
{
var jsonOptions = new JsonSerializerOptions();
jsonOptions.Converters.Add(new JsonStringEnumConverter());
jsonOptions.PropertyNameCaseInsensitive = true;

var jobStatusTask = Task.Run(async () =>
{
var status = SyncJobStatus.Pending;

while (status != SyncJobStatus.Completed)
{
await Task.Delay(200);
var jobResponse = await Client.GetAsync(jobUri);
var syncJob = await jobResponse.Content.ReadFromJsonAsync<SyncJobResponse>(jsonOptions);
if (syncJob != null) status = syncJob.Status;
}
});

var winningTask = await Task.WhenAny(
jobStatusTask,
Task.Delay(TimeSpan.FromMinutes(5)));

if (winningTask != jobStatusTask)
{
Assert.Fail("Waiting for job to complete timed out!");
}

}

protected Task<HttpResponseMessage> MakeSyncDecisionsRequest(SyncDecisionsCommand command)
{
return PostCommand(command, "/sync/decisions");
}

protected Task<HttpResponseMessage> MakeSyncNotificationsRequest(SyncNotificationsCommand command)
{
return PostCommand(command, "/sync/import-notifications");
}

protected Task<HttpResponseMessage> MakeSyncClearanceRequest(SyncClearanceRequestsCommand command)
{
return PostCommand(command, "/sync/clearance-requests");
Factory.CreateBtmsClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });

}

protected Task<HttpResponseMessage> MakeSyncGmrsRequest(SyncGmrsCommand command)
{
return PostCommand(command, "/sync/gmrs");

}

private async Task<HttpResponseMessage> PostCommand<T>(T command, string uri)
{
var jsonData = JsonSerializer.Serialize(command);
HttpContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");

//Act
var response = await Client.PostAsync(uri, content);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.Accepted);

//get job id and wait for job to be completed
var jobUri = response.Headers.Location;
if (jobUri != null) await WaitOnJobCompleting(jobUri);

return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<ItemGroup>
<ProjectReference Include="..\Btms.Model\Btms.Model.csproj" />
<ProjectReference Include="..\Btms.Backend\Btms.Backend.csproj" />
<ProjectReference Include="..\TestDataGenerator\TestDataGenerator.csproj" />
</ItemGroup>

</Project>
56 changes: 56 additions & 0 deletions Btms.Backend.IntegrationTests/DecisionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Diagnostics.CodeAnalysis;
using Btms.Common.Extensions;
using Btms.Model;
using Btms.SyncJob;
using Btms.Backend.IntegrationTests.JsonApiClient;
using FluentAssertions;
using System.Net;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Btms.Backend.IntegrationTests.Extensions;
using Btms.Backend.IntegrationTests.Helpers;
using Btms.Business.Commands;
using Btms.Types.Alvs;
using TestDataGenerator.Scenarios;
using Json.More;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;

namespace Btms.Backend.IntegrationTests;

[Trait("Category", "Integration")]
public class DecisionTests(TestDataGeneratorFactory factory, ITestOutputHelper testOutputHelper)
: BaseApiTests(factory, testOutputHelper, "DecisionTests"), IClassFixture<TestDataGeneratorFactory>
{

[Fact]
public async Task SimpleChedPScenario_ShouldBeLinkedAndMatchDecision()
{
// Arrange
var loadedData = await factory.GenerateAndLoadTestData(Client, "One");

var chedPMovement = loadedData.Single(d =>
d is { generator: ChedPSimpleMatchScenarioGenerator, message: AlvsClearanceRequest })
.message as AlvsClearanceRequest;

// Act
var jsonClientResponse = Client.AsJsonApiClient().GetById(chedPMovement!.Header!.EntryReference!, "api/movements");

// Assert
jsonClientResponse.Should().NotBeNull();
jsonClientResponse.Data.Relationships!.Count.Should().Be(1);

var movement = jsonClientResponse.GetResourceObject<Movement>();
movement.Decisions.Count.Should().Be(2);
movement.AlvsDecisions.Count.Should().Be(1);

movement.AlvsDecisions.First().Context.DecisionMatched.Should().BeTrue();

// TODO : for some reason whilst jsonClientResponse contains the notification relationship, movement doesn't!
// movement.Relationships.Notifications.Data.Count.Should().Be(1);
}
}
40 changes: 40 additions & 0 deletions Btms.Backend.IntegrationTests/Extensions/DatasetExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TestDataGenerator;
using TestDataGenerator.Config;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Btms.Backend.IntegrationTests.Extensions;

public static class DatasetExtensions
{
public static async Task<List<(ScenarioGenerator generator, int scenario, int dateOffset, int count,object message)>> Generate(this Dataset dataset, IHost app, ITestOutputHelper logger)
{
var output = new List<(ScenarioGenerator generator, int scenario, int dateOffset, int count, object message)>();
var generator = app.Services.GetRequiredService<Generator>();

logger.WriteLine("{0} scenario(s) configured", dataset.Scenarios.Count());

var scenario = 1;

await generator.Cleardown(dataset.RootPath);

foreach (var s in dataset.Scenarios)
{
var generatorResult = await generator.Generate(scenario, s, dataset.RootPath);
var results = generatorResult
.SelectMany(gr => gr.result
.Select(r => (gr.generator, gr.scenario, gr.dateOffset, gr.count, r)));

// generatorResult.SelectMany(r => r.result.GetEnumerator(). (r.generator, r.scenario, r.dateOffset, r.count, ))
output.AddRange(results);
scenario++;
}

logger.WriteLine("{0} Done", dataset.Name);

return output;
}

}
40 changes: 15 additions & 25 deletions Btms.Backend.IntegrationTests/GmrTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,30 @@ namespace Btms.Backend.IntegrationTests;

[Trait("Category", "Integration")]
public class GmrTests :
IClassFixture<IntegrationTestsApplicationFactory>, IAsyncLifetime
IClassFixture<ApplicationFactory>, IAsyncLifetime
{
private readonly HttpClient client;
private readonly BtmsClient _client;
private IIntegrationTestsApplicationFactory _factory;

public GmrTests(IntegrationTestsApplicationFactory factory, ITestOutputHelper testOutputHelper)
public GmrTests(ApplicationFactory factory, ITestOutputHelper testOutputHelper)
{
factory.TestOutputHelper = testOutputHelper;
factory.DatabaseName = "GmrTests";
client = factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });
var credentials = "IntTest:Password";
var credentialsAsBytes = Encoding.UTF8.GetBytes(credentials.ToCharArray());
var encodedCredentials = Convert.ToBase64String(credentialsAsBytes);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(BasicAuthenticationDefaults.AuthenticationScheme, encodedCredentials);
_client = factory.CreateBtmsClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });
// _client = factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });
// var credentials = "IntTest:Password";
// var credentialsAsBytes = Encoding.UTF8.GetBytes(credentials.ToCharArray());
// var encodedCredentials = Convert.ToBase64String(credentialsAsBytes);
// _client.DefaultRequestHeaders.Authorization =
// new AuthenticationHeaderValue(BasicAuthenticationDefaults.AuthenticationScheme, encodedCredentials);
_factory = factory;
}

public async Task InitializeAsync()
{
await IntegrationTestsApplicationFactory.ClearDb(client);
await _client.ClearDb();

await MakeSyncGmrsRequest(new SyncGmrsCommand
await _client.MakeSyncGmrsRequest(new SyncGmrsCommand
{
SyncPeriod = SyncPeriod.All,
RootFolder = "SmokeTest"
Expand All @@ -48,7 +51,7 @@ await MakeSyncGmrsRequest(new SyncGmrsCommand
public void FetchSingleGmrTest()
{
//Act
var jsonClientResponse = client.AsJsonApiClient().GetById("GMRAPOQSPDUG", "api/gmrs");
var jsonClientResponse = _client.AsJsonApiClient().GetById("GMRAPOQSPDUG", "api/gmrs");

// Assert
jsonClientResponse.Data.Relationships?["customs"]?.Links?.Self.Should().Be("/api/gmr/:id/relationships/import-notifications");
Expand All @@ -58,19 +61,6 @@ public void FetchSingleGmrTest()
jsonClientResponse.Data.Relationships?["customs"]?.Data.ManyValue?[0].Type.Should().Be("import-notifications");
}

private Task<HttpResponseMessage> MakeSyncGmrsRequest(SyncGmrsCommand command)
{
return PostCommand(command, "/sync/gmrs");
}

private Task<HttpResponseMessage> PostCommand<T>(T command, string uri)
{
var jsonData = JsonSerializer.Serialize(command);
HttpContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");

return client.PostAsync(uri, content);
}

public Task DisposeAsync()
{
return Task.CompletedTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@

namespace Btms.Backend.IntegrationTests.Helpers;

public class IntegrationTestsApplicationFactory : WebApplicationFactory<Program>
public interface IIntegrationTestsApplicationFactory
{
ITestOutputHelper TestOutputHelper { get; set; }
string DatabaseName { get; set; }

BtmsClient CreateBtmsClient(WebApplicationFactoryClientOptions options);
// BtmsClient CreateClient();
IMongoDbContext GetDbContext();
// Task ClearDb(BtmsClient client);
}

public class ApplicationFactory : WebApplicationFactory<Program>, IIntegrationTestsApplicationFactory
{
// protected override Bef
protected override void ConfigureWebHost(IWebHostBuilder builder)
Expand Down Expand Up @@ -61,17 +72,27 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
builder.UseEnvironment("Development");
}

internal ITestOutputHelper TestOutputHelper { get; set; } = null!;
public ITestOutputHelper TestOutputHelper { get; set; } = null!;

internal string DatabaseName { get; set; } = null!;
public string DatabaseName { get; set; } = null!;

public IMongoDbContext GetDbContext()
public BtmsClient CreateBtmsClient(WebApplicationFactoryClientOptions options)
{
return Services.CreateScope().ServiceProvider.GetRequiredService<IMongoDbContext>();
return new BtmsClient(base.CreateClient(options));
}

public static async Task ClearDb(HttpClient client)
public IMongoDbContext GetDbContext()
{
await client.GetAsync("mgmt/collections/drop");
return Services.CreateScope().ServiceProvider.GetRequiredService<IMongoDbContext>();
}

// public new BtmsClient CreateClient()
// {
// return base.CreateClient()
// }

// public async Task ClearDb(BtmsClient client)
// {
// await client.GetAsync("mgmt/collections/drop");
// }
}
Loading
Loading