This repository has been archived by the owner on Jul 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
203 additions
and
0 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
backend/src/Logitar.Master.Application/BadRequestException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Logitar.Master.Contracts.Errors; | ||
|
||
namespace Logitar.Master.Application; | ||
|
||
public abstract class BadRequestException : Exception | ||
{ | ||
public abstract Error Error { get; } | ||
|
||
protected BadRequestException(string? message = null, Exception? innerException = null) : base(message, innerException) | ||
{ | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
backend/src/Logitar.Master.Application/Projects/Queries/ReadProjectQuery.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
using Logitar.Master.Contracts.Projects; | ||
using MediatR; | ||
|
||
namespace Logitar.Master.Application.Projects.Queries; | ||
|
||
public record ReadProjectQuery(Guid? Id, string? UniqueKey) : IRequest<Project?>; |
44 changes: 44 additions & 0 deletions
44
backend/src/Logitar.Master.Application/Projects/Queries/ReadProjectQueryHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using Logitar.Master.Contracts.Projects; | ||
using MediatR; | ||
|
||
namespace Logitar.Master.Application.Projects.Queries; | ||
|
||
internal class ReadProjectQueryHandler : IRequestHandler<ReadProjectQuery, Project?> | ||
{ | ||
private readonly IProjectQuerier _projectQuerier; | ||
|
||
public ReadProjectQueryHandler(IProjectQuerier projectQuerier) | ||
{ | ||
_projectQuerier = projectQuerier; | ||
} | ||
|
||
public async Task<Project?> Handle(ReadProjectQuery query, CancellationToken cancellationToken) | ||
{ | ||
Dictionary<Guid, Project> projects = new(capacity: 2); | ||
|
||
if (query.Id.HasValue) | ||
{ | ||
Project? project = await _projectQuerier.ReadAsync(query.Id.Value, cancellationToken); | ||
if (project != null) | ||
{ | ||
projects[project.Id] = project; | ||
} | ||
} | ||
|
||
if (!string.IsNullOrWhiteSpace(query.UniqueKey)) | ||
{ | ||
Project? project = await _projectQuerier.ReadAsync(query.UniqueKey, cancellationToken); | ||
if (project != null) | ||
{ | ||
projects[project.Id] = project; | ||
} | ||
} | ||
|
||
if (projects.Count > 1) | ||
{ | ||
throw TooManyResultsException<Project>.ExpectedSingle(projects.Count); | ||
} | ||
|
||
return projects.Values.SingleOrDefault(); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
backend/src/Logitar.Master.Application/TooManyResultsException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Logitar.Master.Contracts.Errors; | ||
|
||
namespace Logitar.Master.Application; | ||
|
||
public class TooManyResultsException : BadRequestException | ||
{ | ||
private const string ErrorMessage = "There are too many results."; | ||
|
||
public string TypeName | ||
{ | ||
get => (string)Data[nameof(TypeName)]!; | ||
private set => Data[nameof(TypeName)] = value; | ||
} | ||
public int ExpectedCount | ||
{ | ||
get => (int)Data[nameof(ExpectedCount)]!; | ||
private set => Data[nameof(ExpectedCount)] = value; | ||
} | ||
public int ActualCount | ||
{ | ||
get => (int)Data[nameof(ActualCount)]!; | ||
private set => Data[nameof(ActualCount)] = value; | ||
} | ||
|
||
public override Error Error | ||
{ | ||
get | ||
{ | ||
Error error = new(this.GetErrorCode(), ErrorMessage); | ||
error.Add(nameof(ExpectedCount), ExpectedCount.ToString()); | ||
error.Add(nameof(ActualCount), ActualCount.ToString()); | ||
return error; | ||
} | ||
} | ||
|
||
public TooManyResultsException(Type type, int expectedCount, int actualCount) : base(BuildMessage(type, expectedCount, actualCount)) | ||
{ | ||
TypeName = type.GetNamespaceQualifiedName(); | ||
ExpectedCount = expectedCount; | ||
ActualCount = actualCount; | ||
} | ||
|
||
private static string BuildMessage(Type type, int expectedCount, int actualCount) => new ErrorMessageBuilder(ErrorMessage) | ||
.AddData(nameof(TypeName), type.GetNamespaceQualifiedName()) | ||
.AddData(nameof(ExpectedCount), expectedCount) | ||
.AddData(nameof(ActualCount), actualCount) | ||
.Build(); | ||
} | ||
|
||
public class TooManyResultsException<T> : TooManyResultsException | ||
{ | ||
public TooManyResultsException(int expectedCount, int actualCount) : base(typeof(T), expectedCount, actualCount) | ||
{ | ||
} | ||
|
||
public static TooManyResultsException<T> ExpectedSingle(int actualCount) => new(expectedCount: 1, actualCount); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
...sts/Logitar.Master.IntegrationTests/Application/Projects/Queries/ReadProjectQueryTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using Logitar.Master.Contracts.Projects; | ||
using Logitar.Master.Domain.Projects; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Logitar.Master.Application.Projects.Queries; | ||
|
||
[Trait(Traits.Category, Categories.Integration)] | ||
public class ReadProjectQueryTests : IntegrationTests | ||
{ | ||
private readonly IProjectRepository _projectRepository; | ||
|
||
private readonly ProjectAggregate _master; | ||
private readonly ProjectAggregate _portal; | ||
|
||
public ReadProjectQueryTests() : base() | ||
{ | ||
_projectRepository = ServiceProvider.GetRequiredService<IProjectRepository>(); | ||
|
||
_master = new(new UniqueKeyUnit("MASTER")); | ||
_portal = new(new UniqueKeyUnit("PORTAL")); | ||
} | ||
|
||
public override async Task InitializeAsync() | ||
{ | ||
await base.InitializeAsync(); | ||
|
||
await _projectRepository.SaveAsync([_master, _portal]); | ||
} | ||
|
||
[Fact(DisplayName = "It should return null when no project was found.")] | ||
public async Task It_should_return_null_when_no_project_was_found() | ||
{ | ||
ReadProjectQuery query = new(Id: Guid.Empty, UniqueKey: "test"); | ||
Project? project = await Mediator.Send(query); | ||
Assert.Null(project); | ||
} | ||
|
||
[Fact(DisplayName = "It should return the project found by ID.")] | ||
public async Task It_should_return_the_project_found_by_Id() | ||
{ | ||
ReadProjectQuery query = new(Id: _master.Id.ToGuid(), UniqueKey: null); | ||
Project? project = await Mediator.Send(query); | ||
Assert.NotNull(project); | ||
Assert.Equal(_master.Id.ToGuid(), project.Id); | ||
} | ||
|
||
[Fact(DisplayName = "It should return the project found by unique key.")] | ||
public async Task It_should_return_the_project_found_by_unique_key() | ||
{ | ||
ReadProjectQuery query = new(Id: null, UniqueKey: " portal "); | ||
Project? project = await Mediator.Send(query); | ||
Assert.NotNull(project); | ||
Assert.Equal(_portal.Id.ToGuid(), project.Id); | ||
} | ||
|
||
[Fact(DisplayName = "It should throw TooManyResultsException when many projects were found.")] | ||
public async Task It_should_throw_TooManyResultsException_when_many_projects_were_found() | ||
{ | ||
ReadProjectQuery query = new(_master.Id.ToGuid(), UniqueKey: " portal "); | ||
var exception = await Assert.ThrowsAsync<TooManyResultsException<Project>>(async () => await Mediator.Send(query)); | ||
Assert.Equal(1, exception.ExpectedCount); | ||
Assert.Equal(2, exception.ActualCount); | ||
} | ||
} |