Skip to content

Commit

Permalink
Refactored vanilla Marten command handling to AggregateHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Feb 5, 2024
1 parent f6bcdd4 commit f7f147a
Show file tree
Hide file tree
Showing 19 changed files with 152 additions and 282 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Helpdesk.Api.Incidents;
using Helpdesk.Api.Incidents.AcknowledgingResolution;
using Helpdesk.Api.Tests.Incidents.Fixtures;
using Xunit;
using static Ogooreck.API.ApiSpecification;

namespace Helpdesk.Api.Tests.Incidents;

public class AcknowledgeResolutionIncidentTests: IClassFixture<ApiWithResolvedIncident>
public class AcknowledgeResolutionIncidentTests(ApiWithResolvedIncident API):
IClassFixture<ApiWithResolvedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -15,6 +17,7 @@ public class AcknowledgeResolutionIncidentTests: IClassFixture<ApiWithResolvedIn
.When(
POST,
URI($"/api/customers/{API.Incident.CustomerId}/incidents/{API.Incident.Id}/acknowledge"),
BODY(new AcknowledgeResolutionRequest(API.Incident.Id)),
HEADERS(IF_MATCH(2))
)
.Then(OK)
Expand All @@ -32,8 +35,4 @@ API.Incident with
}
)
);

private readonly ApiWithResolvedIncident API;

public AcknowledgeResolutionIncidentTests(ApiWithResolvedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Helpdesk.Api.Incidents.AssigningAgent;
using Helpdesk.Api.Tests.Incidents.Fixtures;
using Xunit;
using static Ogooreck.API.ApiSpecification;

namespace Helpdesk.Api.Tests.Incidents;

public class AssignAgentToIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class AssignAgentToIncidentTests(ApiWithLoggedIncident API):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -15,7 +17,8 @@ await API
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{API.Incident.Id}/assign"),
HEADERS(IF_MATCH(1))
HEADERS(IF_MATCH(1)),
BODY(new AssignAgentToIncidentRequest(API.Incident.Id))
)
.Then(OK)
.And()
Expand All @@ -29,7 +32,4 @@ await API
}

private readonly Guid agentId = Guid.NewGuid();
private readonly ApiWithLoggedIncident API;

public AssignAgentToIncidentTests(ApiWithLoggedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

namespace Helpdesk.Api.Tests.Incidents;

public class CategoriseIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class CategoriseIncidentTests(ApiWithLoggedIncident API):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand Down Expand Up @@ -36,7 +37,4 @@ await API

private readonly Guid agentId = Guid.NewGuid();
private readonly IncidentCategory category = new Faker().PickRandom<IncidentCategory>();
private readonly ApiWithLoggedIncident API;

public CategoriseIncidentTests(ApiWithLoggedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Helpdesk.Api.Incidents;
using Helpdesk.Api.Incidents.Closing;
using Helpdesk.Api.Tests.Incidents.Fixtures;
using Xunit;
using static Ogooreck.API.ApiSpecification;

namespace Helpdesk.Api.Tests.Incidents;

public class CloseIncidentTests: IClassFixture<ApiWithAcknowledgedIncident>
public class CloseIncidentTests(ApiWithAcknowledgedIncident API):
IClassFixture<ApiWithAcknowledgedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -16,6 +18,7 @@ await API
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{API.Incident.Id}/close"),
BODY(new CloseIncidentRequest(API.Incident.Id)),
HEADERS(IF_MATCH(3))
)
.Then(OK);
Expand All @@ -31,8 +34,5 @@ await API
);
}

private readonly ApiWithAcknowledgedIncident API;
private Guid agentId = Guid.NewGuid();

public CloseIncidentTests(ApiWithAcknowledgedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Bogus;
using Bogus.DataSets;
using Helpdesk.Api.Incidents;
using Helpdesk.Api.Incidents.AcknowledgingResolution;
using Helpdesk.Api.Incidents.GettingDetails;
using Helpdesk.Api.Incidents.Logging;
using Helpdesk.Api.Incidents.Resolving;
Expand Down Expand Up @@ -83,7 +84,7 @@ ResolutionType resolutionType
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{incidentId}/resolve"),
BODY(new ResolveIncidentRequest(resolutionType)),
BODY(new ResolveIncidentRequest(incidentId, resolutionType)),
HEADERS(IF_MATCH(1))
)
.Then(OK);
Expand All @@ -97,6 +98,7 @@ Guid customerId
.When(
POST,
URI($"/api/customers/{customerId}/incidents/{incidentId}/acknowledge"),
BODY(new AcknowledgeResolutionRequest(incidentId)),
HEADERS(IF_MATCH(2))
)
.Then(OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

namespace Helpdesk.Api.Tests.Incidents;

public class LogIncidentsTests: IClassFixture<ApiSpecification<Program>>
public class LogIncidentsTests(ApiSpecification<Program> API):
IClassFixture<ApiSpecification<Program>>
{
[Fact]
public Task LogIncident_ShouldSucceed() =>
Expand Down Expand Up @@ -38,10 +39,6 @@ public class LogIncidentsTests: IClassFixture<ApiSpecification<Program>>
)
);

public LogIncidentsTests(ApiSpecification<Program> api) => API = api;

private readonly ApiSpecification<Program> API;

private readonly Guid CustomerId = Guid.NewGuid();

private readonly Contact Contact = new Faker<Contact>().CustomInstantiator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

namespace Helpdesk.Api.Tests.Incidents;

public class PrioritiseIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class PrioritiseIncidentTests(ApiWithLoggedIncident API):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -18,7 +19,7 @@ await API
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{API.Incident.Id}/priority"),
BODY(new PrioritiseIncidentRequest(priority)),
BODY(new PrioritiseIncidentRequest(API.Incident.Id, priority)),
HEADERS(IF_MATCH(1))
)
.Then(OK);
Expand All @@ -40,8 +41,4 @@ API.Incident with

private readonly Guid agentId = Guid.NewGuid();
private readonly IncidentPriority priority = new Faker().PickRandom<IncidentPriority>();
private readonly ApiWithLoggedIncident API;

public PrioritiseIncidentTests(ApiWithLoggedIncident api) => API = api;

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Bogus;
using Bogus.DataSets;
using Helpdesk.Api.Incidents;
using Helpdesk.Api.Incidents.GettingDetails;
using Helpdesk.Api.Incidents.RecordingAgentResponse;
using Helpdesk.Api.Tests.Incidents.Fixtures;
Expand All @@ -9,29 +8,30 @@

namespace Helpdesk.Api.Tests.Incidents;

public class RecordAgentResponseToIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class RecordAgentResponseToIncidentTests(ApiWithLoggedIncident api):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
public async Task RecordAgentResponseCommand_RecordsResponse()
{
await API
await api
.Given()
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{API.Incident.Id}/responses"),
BODY(new RecordAgentResponseToIncidentRequest(content, visibleToCustomer)),
URI($"/api/agents/{agentId}/incidents/{api.Incident.Id}/responses"),
BODY(new RecordAgentResponseToIncidentRequest(api.Incident.Id, content, visibleToCustomer)),
HEADERS(IF_MATCH(1))
)
.Then(OK);

await API
await api
.Given()
.When(GET, URI($"/api/incidents/{API.Incident.Id}"))
.When(GET, URI($"/api/incidents/{api.Incident.Id}"))
.Then(
OK,
RESPONSE_BODY(
API.Incident with
api.Incident with
{
Notes = new[]
{
Expand All @@ -46,7 +46,4 @@ API.Incident with
private readonly Guid agentId = Guid.NewGuid();
private readonly string content = new Lorem().Sentence();
private readonly bool visibleToCustomer = new Faker().Random.Bool();
private readonly ApiWithLoggedIncident API;

public RecordAgentResponseToIncidentTests(ApiWithLoggedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Bogus.DataSets;
using Helpdesk.Api.Incidents;
using Helpdesk.Api.Incidents.GettingDetails;
using Helpdesk.Api.Incidents.RecordingCustomerResponse;
using Helpdesk.Api.Tests.Incidents.Fixtures;
Expand All @@ -8,7 +7,8 @@

namespace Helpdesk.Api.Tests.Incidents;

public class RecordCustomerResponseToIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class RecordCustomerResponseToIncidentTests(ApiWithLoggedIncident API):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -19,7 +19,7 @@ await API
.When(
POST,
URI($"/api/customers/{customerId}/incidents/{API.Incident.Id}/responses"),
BODY(new RecordCustomerResponseToIncidentRequest(content)),
BODY(new RecordCustomerResponseToIncidentRequest(API.Incident.Id, content)),
HEADERS(IF_MATCH(1))
)
.Then(OK);
Expand All @@ -33,7 +33,7 @@ await API
API.Incident with
{
Notes =
new[] { new IncidentNote(IncidentNoteType.FromCustomer, customerId, content, true) },
[new IncidentNote(IncidentNoteType.FromCustomer, customerId, content, true)],
Version = 2
}
)
Expand All @@ -42,7 +42,4 @@ API.Incident with

private readonly Guid customerId = Guid.NewGuid();
private readonly string content = new Lorem().Sentence();
private readonly ApiWithLoggedIncident API;

public RecordCustomerResponseToIncidentTests(ApiWithLoggedIncident api) => API = api;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

namespace Helpdesk.Api.Tests.Incidents;

public class ResolveIncidentTests: IClassFixture<ApiWithLoggedIncident>
public class ResolveIncidentTests(ApiWithLoggedIncident API):
IClassFixture<ApiWithLoggedIncident>
{
[Fact]
[Trait("Category", "Acceptance")]
Expand All @@ -18,7 +19,7 @@ await API
.When(
POST,
URI($"/api/agents/{agentId}/incidents/{API.Incident.Id}/resolve"),
BODY(new ResolveIncidentRequest(resolutionType)),
BODY(new ResolveIncidentRequest(API.Incident.Id, resolutionType)),
HEADERS(IF_MATCH(1))
)
.Then(OK);
Expand All @@ -39,7 +40,4 @@ await API

private readonly Guid agentId = Guid.NewGuid();
private readonly ResolutionType resolutionType = new Faker().PickRandom<ResolutionType>();
private readonly ApiWithLoggedIncident API;

public ResolveIncidentTests(ApiWithLoggedIncident api) => API = api;
}
4 changes: 4 additions & 0 deletions Sample/Helpdesk.Wolverine/Helpdesk.Api/Helpdesk.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
<PackageReference Include="WolverineFx.Marten" Version="2.0.0-alpha.1" />
<PackageReference Include="WolverineFx.Http" Version="2.0.0-alpha.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Internal\Generated\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,47 +1,31 @@
using Helpdesk.Api.Core.Http;
using Helpdesk.Api.Core.Marten;
using Marten;
using Microsoft.AspNetCore.Mvc;
using Wolverine.Http;
using Wolverine.Marten;
using static Microsoft.AspNetCore.Http.TypedResults;
using static Helpdesk.Api.Core.Http.ETagExtensions;
using static System.DateTimeOffset;

namespace Helpdesk.Api.Incidents.AcknowledgingResolution;

public static class AcknowledgeResolutionEndpoint
{
[AggregateHandler]
[WolverinePost("/api/customers/{customerId:guid}/incidents/{incidentId:guid}/acknowledge")]
public static async Task<IResult> AcknowledgeResolution
public static (IResult, Events) AcknowledgeResolution
(
IDocumentSession documentSession,
Guid incidentId,
Guid customerId,
[FromIfMatchHeader] string eTag,
CancellationToken ct
AcknowledgeResolutionRequest request,
Incident incident,
[FromRoute] Guid agentId,
[FromRoute] Guid incidentId,
//TODO: [FromIfMatchHeader] string eTag,
DateTimeOffset now
)
{
await documentSession.GetAndUpdate<Incident>(incidentId, ToExpectedVersion(eTag),
state => Handle(state, new AcknowledgeResolution(incidentId, customerId, Now)), ct);

return Ok();
}

public static ResolutionAcknowledgedByCustomer Handle(
Incident current,
AcknowledgeResolution command
)
{
if (current.Status is not IncidentStatus.Resolved)
if (incident.Status is not IncidentStatus.Resolved)
throw new InvalidOperationException("Only resolved incident can be acknowledged");

var (incidentId, acknowledgedBy, now) = command;

return new ResolutionAcknowledgedByCustomer(incidentId, acknowledgedBy, now);
return (Ok(), [new ResolutionAcknowledgedByCustomer(incidentId, agentId, now)]);
}
}

public record AcknowledgeResolution(
Guid IncidentId,
Guid AcknowledgedBy,
DateTimeOffset Now
public record AcknowledgeResolutionRequest(
Guid IncidentId // TODO: meh
);
Loading

0 comments on commit f7f147a

Please sign in to comment.