diff --git a/src/2-Services/Owners/Api/Owners.Read.Api/Features/Organizations/GetOrganizationReportById/GetOrganizationReportByIdHandler.cs b/src/2-Services/Owners/Api/Owners.Read.Api/Features/Organizations/GetOrganizationReportById/GetOrganizationReportByIdHandler.cs index 8715f86ff..38de092d6 100644 --- a/src/2-Services/Owners/Api/Owners.Read.Api/Features/Organizations/GetOrganizationReportById/GetOrganizationReportByIdHandler.cs +++ b/src/2-Services/Owners/Api/Owners.Read.Api/Features/Organizations/GetOrganizationReportById/GetOrganizationReportByIdHandler.cs @@ -75,15 +75,9 @@ public async Task Handle(GetOrganizationReportByIdRequest #endregion #region Board Reports - var boards = new List(); - var boardsGrpcCall = _getBoardsByOrganizationIdGrpcServiceClient.Handle( - new GetBoardsByOrganizationIdGrpcRequest { OrganizationId = organization.Id } - ); - - await foreach (var response in boardsGrpcCall.ResponseStream.ReadAllAsync()) - boards.Add(_mapper.Map(response)); - organizationReportDto.BoardsCount = boards?.Count ?? 0; + var boards = (await GetBoardsAsync(organization.Id)).ToList(); + organizationReportDto.BoardsCount = boards.Any() ? boards.Count : 0; #endregion #region Task Reports @@ -198,6 +192,19 @@ private async Task> GetTasksAsync(string cardId) return tasks; } + private async Task> GetBoardsAsync(string organizationId) + { + var boards = new List(); + var boardsGrpcCall = _getBoardsByOrganizationIdGrpcServiceClient.Handle( + new GetBoardsByOrganizationIdGrpcRequest { OrganizationId = organizationId } + ); + + await foreach (var response in boardsGrpcCall.ResponseStream.ReadAllAsync()) + boards.Add(_mapper.Map(response)); + + return boards; + } + private GetCardDto MapToCard(GetCardGrpcResponse cardGrpcResponse) { return _mapper.Map(cardGrpcResponse); diff --git a/src/2-Services/Owners/Api/Owners.Read.Api/Infrastructure/Mapper/MappingProfile.cs b/src/2-Services/Owners/Api/Owners.Read.Api/Infrastructure/Mapper/MappingProfile.cs index cde45001e..7a3c48194 100644 --- a/src/2-Services/Owners/Api/Owners.Read.Api/Infrastructure/Mapper/MappingProfile.cs +++ b/src/2-Services/Owners/Api/Owners.Read.Api/Infrastructure/Mapper/MappingProfile.cs @@ -1,9 +1,13 @@ using AutoMapper; using Google.Protobuf.WellKnownTypes; +using System; +using TaskoMask.BuildingBlocks.Contracts.Dtos.Boards; +using TaskoMask.BuildingBlocks.Contracts.Dtos.Cards; using TaskoMask.BuildingBlocks.Contracts.Dtos.Common; using TaskoMask.BuildingBlocks.Contracts.Dtos.Organizations; using TaskoMask.BuildingBlocks.Contracts.Dtos.Owners; using TaskoMask.BuildingBlocks.Contracts.Dtos.Projects; +using TaskoMask.BuildingBlocks.Contracts.Dtos.Tasks; using TaskoMask.BuildingBlocks.Contracts.Protos; using TaskoMask.Services.Owners.Read.Api.Domain; @@ -23,6 +27,27 @@ public MappingProfile() CreateMap(); + CreateMap() + .ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description ?? string.Empty)) + .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name ?? string.Empty)) + .ForMember(dest => dest.ProjectId, opt => opt.MapFrom(src => src.ProjectId ?? string.Empty)) + .ForMember(dest => dest.OrganizationName, opt => opt.MapFrom(src => src.OrganizationName ?? string.Empty)) + .ForMember(dest => dest.ProjectName, opt => opt.MapFrom(src => src.ProjectName ?? string.Empty)) + .ForMember(dest => dest.OwnerId, opt => opt.MapFrom(src => src.OwnerId ?? string.Empty)) + .ForMember(dest => dest.OrganizationId, opt => opt.MapFrom(src => src.OrganizationId ?? string.Empty)); + + CreateMap() + .ForMember(dest => dest.CreateDateTime, opt => opt.MapFrom(src => ConvertTimestamp(src.CreateDateTime))) + .ForMember(dest => dest.CreateDateTimeString, opt => opt.MapFrom(src => src.CreateDateTimeString ?? string.Empty)) + .ForMember(dest => dest.ModifiedDateTime, opt => opt.MapFrom(src => ConvertTimestamp(src.ModifiedDateTime))) + .ForMember(dest => dest.ModifiedDateTimeString, opt => opt.MapFrom(src => src.ModifiedDateTimeString ?? string.Empty)) + .ForMember(dest => dest.CreateDay, opt => opt.MapFrom(src => src.CreateDay)) + .ForMember(dest => dest.CreateMonth, opt => opt.MapFrom(src => src.CreateMonth)) + .ForMember(dest => dest.CreateYear, opt => opt.MapFrom(src => src.CreateYear)); + + CreateMap(); + CreateMap(); + CreateMap() .ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description ?? string.Empty)); @@ -31,4 +56,16 @@ public MappingProfile() CreateMap() .ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description ?? string.Empty)); } + + private DateTime? ConvertTimestamp(Timestamp timestamp) + { + try + { + return timestamp.ToDateTime(); + } + catch + { + return null; + } + } } diff --git a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Features/Organizations/GetOrganizationReportByIdTests.cs b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Features/Organizations/GetOrganizationReportByIdTests.cs index 23b30e792..ffca5b265 100644 --- a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Features/Organizations/GetOrganizationReportByIdTests.cs +++ b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Features/Organizations/GetOrganizationReportByIdTests.cs @@ -1,6 +1,10 @@ -using Moq; +using AutoBogus; +using Grpc.Core; +using Moq; using TaskoMask.BuildingBlocks.Contracts.Protos; +using TaskoMask.Services.Owners.Read.Api.Features.Organizations.GetOrganizationReportById; using TaskoMask.Services.Owners.Read.IntegrationTests.Fixtures; +using TaskoMask.Services.Owners.Read.IntegrationTests.TestData; using Xunit; namespace TaskoMask.Services.Owners.Read.IntegrationTests.Features.Organizations; @@ -11,51 +15,113 @@ public class GetOrganizationReportByIdTests { #region Fields private readonly OrganizationCollectionFixture _fixture; - private readonly Mock _mockBoardsClient; - private readonly Mock _mockCardsClient; - private readonly Mock _mockTasksClient; + #endregion #region Ctor public GetOrganizationReportByIdTests(OrganizationCollectionFixture fixture) { _fixture = fixture; - _mockBoardsClient = new Mock(); - _mockCardsClient = new Mock(); - _mockTasksClient = new Mock(); } #endregion #region Test Methods - //[Fact] - //public async Task OrganizationReport_are_fetched_by_Id() - //{ - // //Arrange - // var expectedOrganization = OrganizationObjectMother.GetOrganization(); - // await _fixture.SeedOrganizationAsync(expectedOrganization); - // var getOrganizationsReportByIdHandler = new GetOrganizationReportByIdHandler( - // _fixture._dbContext, - // _mockBoardsClient.Object, - // _mockCardsClient.Object, - // _mockTasksClient.Object, - // _fixture._mapper - // ); - // var request = new GetOrganizationReportByIdRequest(expectedOrganization.OwnerId); - - // //Act - // var result = await getOrganizationsReportByIdHandler.Handle(request, CancellationToken.None); - - // //Assert - // Assert.NotNull(result); - // Assert.True(result.ProjectsCount >= 0); - // Assert.True(result.BoardsCount >= 0); - // Assert.True(result.ToDoTasksCount >= 0); - // Assert.True(result.DoingTasksCount >= 0); - // Assert.True(result.DoneTasksCount >= 0); - // Assert.True(result.BacklogTasksCount >= 0); - //} + [Fact] + public async Task OrganizationReport_is_fetched_by_Id() + { + // Arrange + var expectedOrganization = OrganizationObjectMother.GetOrganization(); + await _fixture.SeedOrganizationAsync(expectedOrganization); + + var dbContext = _fixture._dbContext; + var mapper = _fixture._mapper; + + var mockBoardsClient = new Mock(); + var mockCardsClient = new Mock(); + var mockTasksClient = new Mock(); + + // Setup mock responses + var fakeBoardsResponse = new AutoFaker().Generate(); + var fakeCardsResponse = new AutoFaker().Generate(); + var fakeTasksResponse = new AutoFaker().Generate(); + + + // Create AsyncServerStreamingCall objects for the mocked responses + var fakeBoardsAsyncResponse = new AsyncServerStreamingCall( + GetAsyncStreamReader(fakeBoardsResponse), + Task.FromResult(new Metadata()), + () => Status.DefaultSuccess, + () => new Metadata(), + () => { } + ); + + + var fakeCardsAsyncResponse = new AsyncServerStreamingCall( + GetAsyncStreamReader(fakeCardsResponse), + Task.FromResult(new Metadata()), + () => Status.DefaultSuccess, + () => new Metadata(), + () => { } + ); + + var fakeTasksAsyncResponse = new AsyncServerStreamingCall( + GetAsyncStreamReader(fakeTasksResponse), + Task.FromResult(new Metadata()), + () => Status.DefaultSuccess, + () => new Metadata(), + () => { } + ); + + mockBoardsClient.Setup(client => client.Handle(It.IsAny(), null, null, CancellationToken.None)) + .Returns(fakeBoardsAsyncResponse); + + mockCardsClient.Setup(client => client.Handle(It.IsAny(), null, null, CancellationToken.None)) + .Returns(fakeCardsAsyncResponse); + + mockTasksClient.Setup(client => client.Handle(It.IsAny(), null, null, CancellationToken.None)) + .Returns(fakeTasksAsyncResponse); + + var handler = new GetOrganizationReportByIdHandler( + dbContext, + mockBoardsClient.Object, + mockCardsClient.Object, + mockTasksClient.Object, + mapper + ); + + var request = new GetOrganizationReportByIdRequest(expectedOrganization.Id); + + // Act + var result = await handler.Handle(request, CancellationToken.None); + + // Assert + Assert.NotNull(result); + Assert.True(result.ProjectsCount >= 0); + Assert.True(result.BoardsCount >= 0); + Assert.True(result.ToDoTasksCount >= 0); + Assert.True(result.DoingTasksCount >= 0); + Assert.True(result.DoneTasksCount >= 0); + Assert.True(result.BacklogTasksCount >= 0); + } + + + #endregion + + #region Methods + private static IAsyncStreamReader GetAsyncStreamReader(params T[] responses) + { + var mockStreamReader = new Mock>(); + var queue = new Queue(responses); + + mockStreamReader.Setup(r => r.MoveNext(It.IsAny())) + .ReturnsAsync(() => queue.Count > 0); + + mockStreamReader.Setup(r => r.Current).Returns(() => queue.Dequeue()); + + return mockStreamReader.Object; + } #endregion -} +} \ No newline at end of file diff --git a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Fixtures/TestsBaseFixture.cs b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Fixtures/TestsBaseFixture.cs index 02d3466cb..16f8f23a2 100644 --- a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Fixtures/TestsBaseFixture.cs +++ b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Fixtures/TestsBaseFixture.cs @@ -1,6 +1,7 @@ using AutoMapper; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using TaskoMask.BuildingBlocks.Application.Bus; using TaskoMask.BuildingBlocks.Test.TestBase; using TaskoMask.Services.Owners.Read.Api.Infrastructure.DbContext; using TaskoMask.Services.Owners.Read.Api.Infrastructure.DI; @@ -11,12 +12,14 @@ public abstract class TestsBaseFixture : IntegrationTestsBase { public readonly IMapper _mapper; public readonly OwnerReadDbContext _dbContext; + public readonly IInMemoryBus _inMemoryBus; protected TestsBaseFixture(string dbNameSuffix) : base(dbNameSuffix) { _mapper = GetRequiredService(); _dbContext = GetRequiredService(); + _inMemoryBus = GetRequiredService(); } /// @@ -27,6 +30,7 @@ public override void InitialDatabase() _serviceProvider.InitialDatabase(); } + /// /// /// diff --git a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Owners.Read.Tests.Integration.csproj b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Owners.Read.Tests.Integration.csproj index 34aa39c6b..671d1bdb8 100644 --- a/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Owners.Read.Tests.Integration.csproj +++ b/src/2-Services/Owners/Tests/Owners.Read.Tests.Integration/Owners.Read.Tests.Integration.csproj @@ -9,6 +9,7 @@ +