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

Fix date time handling in chapter 1 #108

Merged
merged 7 commits into from
Apr 2, 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Common.TestEngine.Con
using EvolutionaryArchitecture.Fitnet.Common.Events.EventBus.InMemory;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Time.Testing;

internal static class ConfigurationExtensions
{
Expand Down Expand Up @@ -33,11 +32,6 @@ private static WebApplicationFactory<T> UseSettings<T>(this WebApplicationFactor
}
});

internal static WebApplicationFactory<T> SetFakeSystemClock<T>(this WebApplicationFactory<T> webApplicationFactory, DateTimeOffset fakeDateTimeOffset)
where T : class =>
webApplicationFactory.WithWebHostBuilder(webHostBuilder => webHostBuilder.ConfigureTestServices(services =>
services.AddSingleton<TimeProvider>(new FakeTimeProvider(fakeDateTimeOffset))));

internal static WebApplicationFactory<T> WithFakeEventBus<T>(this WebApplicationFactory<T> webApplicationFactory, IEventBus eventBusMock)
where T : class =>
webApplicationFactory.WithWebHostBuilder(webHostBuilder => webHostBuilder.ConfigureTestServices(services =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Common.TestEngine.Time;

[UsedImplicitly]
internal sealed class FakeTimeProvider(DateTimeOffset? now = null) : TimeProvider
{
private DateTimeOffset TimeNowOffset { get; set; } = now ?? new Faker().Date.RecentOffset().UtcDateTime;

public override DateTimeOffset GetUtcNow() => TimeNowOffset;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Common.TestEngine.Time;

using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;

internal static class TimeExtensions
{
internal static WebApplicationFactory<T> WithTime<T>(
this WebApplicationFactory<T> webApplicationFactory, FakeTimeProvider fakeSystemTimeProvider)
where T : class => webApplicationFactory
.WithWebHostBuilder(builder => builder.ConfigureTestServices(services => services.AddSingleton<TimeProvider>(fakeSystemTimeProvider)));
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
global using Bogus;
global using JetBrains.Annotations;
global using NSubstitute;
global using EvolutionaryArchitecture.Fitnet.IntegrationTests.Common.TestEngine;
global using EvolutionaryArchitecture.Fitnet.IntegrationTests.Common.TestEngine;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Reports.GenerateNewPa

using Common.TestEngine.Configuration;
using Common.TestEngine.IntegrationEvents.Handlers;
using Common.TestEngine.Time;
using Fitnet.Contracts.SignContract.Events;
using Fitnet.Reports;
using Fitnet.Reports.GenerateNewPassesRegistrationsPerMonthReport.Dtos;
Expand All @@ -11,6 +12,7 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Reports.GenerateNewPa
[UsesVerify]
public sealed class GenerateNewPassesPerMonthReportTests : IClassFixture<WebApplicationFactory<Program>>, IClassFixture<DatabaseContainer>
{
private static readonly FakeTimeProvider FakeTimeProvider = new(ReportTestCases.FakeNowDate);
private readonly HttpClient _applicationHttpClient;
private readonly WebApplicationFactory<Program> _applicationInMemoryFactory;

Expand All @@ -19,15 +21,15 @@ public GenerateNewPassesPerMonthReportTests(WebApplicationFactory<Program> appli
{
_applicationInMemoryFactory = applicationInMemoryFactory
.WithContainerDatabaseConfigured(database.ConnectionString!)
.SetFakeSystemClock(ReportTestCases.FakeNowDate);
.WithTime(FakeTimeProvider);

_applicationHttpClient = _applicationInMemoryFactory.CreateClient();
}


[Theory]
[ClassData(typeof(ReportTestCases))]
internal async Task Given_valid_generate_new_report_request_Then_should_return_correct_data(List<PassRegistrationDateRange> passRegistrationDateRanges)
internal async Task Given_valid_generate_new_report_request_Then_should_return_correct_data(
List<PassRegistrationDateRange> passRegistrationDateRanges)
{
// Arrange
await RegisterPasses(passRegistrationDateRanges);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ internal sealed class ReportTestCases : IEnumerable<object[]>

public IEnumerator<object[]> GetEnumerator()
{
yield return new object[]
{
yield return
[
new List<PassRegistrationDateRange>
{
new(new DateTimeOffset(FakeNowDate.Year, 1, 3, 1, 1,1, TimeSpan.Zero), new DateTimeOffset(FakeNowDate.Year, 1, 10 ,1, 1, 1,1, TimeSpan.Zero)),
Expand All @@ -24,8 +24,8 @@ public IEnumerator<object[]> GetEnumerator()
new(new DateTimeOffset(FakeNowDate.Year, 11, 1, 1, 1,1, TimeSpan.Zero), new DateTimeOffset(FakeNowDate.Year, 11, 30 ,1, 1, 1,1, TimeSpan.Zero)),
new(new DateTimeOffset(FakeNowDate.Year, 12, 1, 1, 1,1, TimeSpan.Zero), new DateTimeOffset(FakeNowDate.Year, 12, 31 ,1, 1, 1,1, TimeSpan.Zero))
}
};
];
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ namespace EvolutionaryArchitecture.Fitnet.Contracts.SignContract.Events;

using EvolutionaryArchitecture.Fitnet.Common.Events;

internal record ContractSignedEvent(Guid Id, Guid ContractId, Guid ContractCustomerId, DateTimeOffset SignedAt, DateTimeOffset ExpireAt, DateTimeOffset OccurredDateTime) : IIntegrationEvent
internal record ContractSignedEvent(
Guid Id,
Guid ContractId,
Guid ContractCustomerId,
DateTimeOffset SignedAt,
DateTimeOffset ExpireAt,
DateTimeOffset OccurredDateTime) : IIntegrationEvent
{
internal static ContractSignedEvent Create(Guid contractId, Guid contractCustomerId, DateTimeOffset signedAt, DateTimeOffset expireAt) =>
new(Guid.NewGuid(), contractId, contractCustomerId, signedAt, expireAt, DateTimeOffset.UtcNow);
}
internal static ContractSignedEvent Create(
Guid contractId,
Guid contractCustomerId,
DateTimeOffset signedAt,
DateTimeOffset expireAt,
DateTimeOffset occurredAt) =>
new(Guid.NewGuid(), contractId, contractCustomerId, signedAt, expireAt, occurredAt);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ internal static void MapSignContract(this IEndpointRouteBuilder app) => app.MapP
contract.Sign(request.SignedAt, dateNow);
await persistence.SaveChangesAsync(cancellationToken);

var @event = ContractSignedEvent.Create(contract.Id, contract.CustomerId, contract.SignedAt!.Value,
contract.ExpiringAt!.Value);
var @event = ContractSignedEvent.Create(
contract.Id,
contract.CustomerId,
contract.SignedAt!.Value,
contract.ExpiringAt!.Value,
timeProvider.GetUtcNow());
await bus.PublishAsync(@event, cancellationToken);

return Results.NoContent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ namespace EvolutionaryArchitecture.Fitnet.Offers.Prepare;

internal sealed record OfferPrepareEvent(Guid Id, Guid OfferId, Guid CustomerId, DateTimeOffset OccurredDateTime) : IIntegrationEvent
{
private OfferPrepareEvent(Guid offerId, Guid customerId) : this(Guid.NewGuid(), offerId, customerId, DateTimeOffset.Now)
{
}

internal static OfferPrepareEvent Create(Guid offerId, Guid customerId) => new(offerId, customerId);
}
internal static OfferPrepareEvent Create(Guid offerId, Guid customerId, DateTimeOffset occurredAt) =>
new(Guid.NewGuid(), offerId, customerId, occurredAt);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public async Task Handle(PassExpiredEvent @event, CancellationToken cancellation
persistence.Offers.Add(offer);
await persistence.SaveChangesAsync(cancellationToken);

var offerPreparedEvent = OfferPrepareEvent.Create(offer.Id, offer.CustomerId);
var offerPreparedEvent = OfferPrepareEvent.Create(offer.Id, offer.CustomerId, timeProvider.GetUtcNow());
await eventBus.PublishAsync(offerPreparedEvent, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ namespace EvolutionaryArchitecture.Fitnet.Passes.MarkPassAsExpired.Events;

internal record PassExpiredEvent(Guid Id, Guid PassId, Guid CustomerId, DateTimeOffset OccurredDateTime) : IIntegrationEvent
{
internal static PassExpiredEvent Create(Guid passId, Guid customerId) => new(Guid.NewGuid(), passId, customerId, DateTimeOffset.Now);
}
internal static PassExpiredEvent Create(Guid passId, Guid customerId, DateTimeOffset occurredAt) =>
new(Guid.NewGuid(), passId, customerId, occurredAt);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ internal static void MapMarkPassAsExpired(this IEndpointRouteBuilder app) => app
var nowDate = timeProvider.GetUtcNow();
pass.MarkAsExpired(nowDate);
await persistence.SaveChangesAsync(cancellationToken);
await eventBus.PublishAsync(PassExpiredEvent.Create(pass.Id, pass.CustomerId), cancellationToken);
await eventBus.PublishAsync(
PassExpiredEvent.Create(pass.Id, pass.CustomerId, timeProvider.GetUtcNow()),
cancellationToken);

return Results.NoContent();
})
Expand Down
Loading