diff --git a/.github/workflows/build_microservices.yml b/.github/workflows/build_microservices.yml index 930a6df87..ff3101d08 100644 --- a/.github/workflows/build_microservices.yml +++ b/.github/workflows/build_microservices.yml @@ -16,6 +16,8 @@ jobs: - project: 'MiniSpace.APIGateway/src/MiniSpace.APIGateway' - project: 'MiniSpace.Services.Identity/src/MiniSpace.Services.Identity.Api' test_dir: 'MiniSpace.Services.Identity/tests' + - project: 'MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api' + test_dir: 'MiniSpace.Services.Posts/tests' - project: 'MiniSpace.Services.Comments/src/MiniSpace.Services.Comments.Api' test_dir: 'MiniSpace.Services.Comments/tests' - project: 'MiniSpace.Web/src/MiniSpace.Web' @@ -53,6 +55,6 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} files: '**/coverage.cobertura.xml' - slug: SaintAngeLs/p_software_engineering_2 + slug: SaintAngeLs/distributed_minispace commit: ${{ github.event.pull_request.base.sha }} # fail_ci_if_error: true diff --git a/.github/workflows/cloud_deploy.yml b/.github/workflows/cloud_deploy.yml index 8da1e4996..4694a98f5 100644 --- a/.github/workflows/cloud_deploy.yml +++ b/.github/workflows/cloud_deploy.yml @@ -3,10 +3,10 @@ name: Deploy to Cloud on: push: branches: - - dev + - main pull_request: branches: - - dev + - main jobs: deploy: diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfo.cs b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfo.cs index ccb80173f..b8c367ff9 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfo.cs +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("MiniSpace.Services.Notifications.Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e469fbdaa8f94ad32f18bc8ef20510fd62b15985")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+60d80bd60074e10f1cb39a7857095b65f8213b6b")] [assembly: System.Reflection.AssemblyProductAttribute("MiniSpace.Services.Notifications.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("MiniSpace.Services.Notifications.Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfoInputs.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfoInputs.cache index f0890d716..9b46351fb 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfoInputs.cache +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.AssemblyInfoInputs.cache @@ -1 +1 @@ -2d6a02b206ac77283cc075e6254c51c91df1cc844dbe932e799219bd1858d708 +31d3d94a6fa27c086d9707313d1f0be1fb13fd6bcd249b38361e7fac38610470 diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.csproj.AssemblyReference.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.csproj.AssemblyReference.cache index 027688926..1ec47ab0e 100644 Binary files a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.csproj.AssemblyReference.cache and b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Api/obj/Debug/net8.0/MiniSpace.Services.Notifications.Api.csproj.AssemblyReference.cache differ diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfo.cs b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfo.cs index ba1a11190..f7d2be4c7 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfo.cs +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("MiniSpace.Services.Notifications.Application")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e469fbdaa8f94ad32f18bc8ef20510fd62b15985")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+60d80bd60074e10f1cb39a7857095b65f8213b6b")] [assembly: System.Reflection.AssemblyProductAttribute("MiniSpace.Services.Notifications.Application")] [assembly: System.Reflection.AssemblyTitleAttribute("MiniSpace.Services.Notifications.Application")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfoInputs.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfoInputs.cache index 0775574dd..f55ea9411 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfoInputs.cache +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.AssemblyInfoInputs.cache @@ -1 +1 @@ -72ac1d3825741bd508e9ff6ffaf58fa81268523d2a753710d887fc83a9d80b9a +8b3e043d4a8610c77bcbe2160d6b95b7942634686dac3d3841cdef59e617bd04 diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.csproj.AssemblyReference.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.csproj.AssemblyReference.cache index f85758ab5..f06992374 100644 Binary files a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.csproj.AssemblyReference.cache and b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Application/obj/Debug/net8.0/MiniSpace.Services.Notifications.Application.csproj.AssemblyReference.cache differ diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfo.cs b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfo.cs index d0aead76b..362885395 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfo.cs +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("MiniSpace.Services.Notifications.Core")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e469fbdaa8f94ad32f18bc8ef20510fd62b15985")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+60d80bd60074e10f1cb39a7857095b65f8213b6b")] [assembly: System.Reflection.AssemblyProductAttribute("MiniSpace.Services.Notifications.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("MiniSpace.Services.Notifications.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfoInputs.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfoInputs.cache index c8c66858d..4f3eeef42 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfoInputs.cache +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Core/obj/Debug/net8.0/MiniSpace.Services.Notifications.Core.AssemblyInfoInputs.cache @@ -1 +1 @@ -af7e27a1b036cf20b19f769f736410eb4de82166981876644172854c53396ed6 +5dd7b0640cf1bb26d53f06d7da4a1fccb31b33f3ce01be304f8a958930eaee66 diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfo.cs b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfo.cs index 1fc010238..1b6eab5ad 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfo.cs +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("MiniSpace.Services.Notifications.Infrastructure")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e469fbdaa8f94ad32f18bc8ef20510fd62b15985")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+60d80bd60074e10f1cb39a7857095b65f8213b6b")] [assembly: System.Reflection.AssemblyProductAttribute("MiniSpace.Services.Notifications.Infrastructure")] [assembly: System.Reflection.AssemblyTitleAttribute("MiniSpace.Services.Notifications.Infrastructure")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfoInputs.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfoInputs.cache index a53b56445..2d7ce697b 100644 --- a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfoInputs.cache +++ b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.AssemblyInfoInputs.cache @@ -1 +1 @@ -06935d4026aba0069abdca20ba9959a7f7e14e8e87a965f3b7301324f870eec5 +1cdfc024d737e449203c0f0f3550021dfc68bcff58a6f7d5947cc08a0083e939 diff --git a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.csproj.AssemblyReference.cache b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.csproj.AssemblyReference.cache index 1c7ea12d3..5244840ef 100644 Binary files a/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.csproj.AssemblyReference.cache and b/MiniSpace.Services.Notifications/src/MiniSpace.Services.Notifications.Infrastructure/obj/Debug/net8.0/MiniSpace.Services.Notifications.Infrastructure.csproj.AssemblyReference.cache differ diff --git a/MiniSpace.Services.Posts/.gitignore b/MiniSpace.Services.Posts/.gitignore index c1aafb511..fffd35c7b 100644 --- a/MiniSpace.Services.Posts/.gitignore +++ b/MiniSpace.Services.Posts/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# VSCode +.vscode/ + # User-specific files *.suo *.user diff --git a/MiniSpace.Services.Posts/MiniSpace.Services.Posts.sln b/MiniSpace.Services.Posts/MiniSpace.Services.Posts.sln index 468fc6e92..031553aa5 100644 --- a/MiniSpace.Services.Posts/MiniSpace.Services.Posts.sln +++ b/MiniSpace.Services.Posts/MiniSpace.Services.Posts.sln @@ -13,6 +13,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSpace.Services.Posts.Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSpace.Services.Posts.Infrastructure", "src\MiniSpace.Services.Posts.Infrastructure\MiniSpace.Services.Posts.Infrastructure.csproj", "{515F6D6B-FB63-40F7-8173-2B94031F29B1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSpace.Services.Posts.Application.UnitTests", "tests\MiniSpace.Services.Posts.Application.UnitTests\MiniSpace.Services.Posts.Application.UnitTests.csproj", "{63DF71AF-1D31-4A4D-8127-9B8EB359889D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSpace.Services.Posts.Core.UnitTests", "tests\MiniSpace.Services.Posts.Core.UnitTests\MiniSpace.Services.Posts.Core.UnitTests.csproj", "{38556B4C-90E1-453F-8BA7-C0699577A521}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniSpace.Services.Posts.Infrastructure.UnitTests", "tests\MiniSpace.Services.Posts.Infrastructure.UnitTests\MiniSpace.Services.Posts.Infrastructure.UnitTests.csproj", "{641E0BF5-8BAA-4ECC-9EA7-18CA3D763166}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -38,11 +44,26 @@ Global {515F6D6B-FB63-40F7-8173-2B94031F29B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {515F6D6B-FB63-40F7-8173-2B94031F29B1}.Release|Any CPU.ActiveCfg = Release|Any CPU {515F6D6B-FB63-40F7-8173-2B94031F29B1}.Release|Any CPU.Build.0 = Release|Any CPU + {63DF71AF-1D31-4A4D-8127-9B8EB359889D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63DF71AF-1D31-4A4D-8127-9B8EB359889D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63DF71AF-1D31-4A4D-8127-9B8EB359889D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63DF71AF-1D31-4A4D-8127-9B8EB359889D}.Release|Any CPU.Build.0 = Release|Any CPU + {38556B4C-90E1-453F-8BA7-C0699577A521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38556B4C-90E1-453F-8BA7-C0699577A521}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38556B4C-90E1-453F-8BA7-C0699577A521}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38556B4C-90E1-453F-8BA7-C0699577A521}.Release|Any CPU.Build.0 = Release|Any CPU + {641E0BF5-8BAA-4ECC-9EA7-18CA3D763166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {641E0BF5-8BAA-4ECC-9EA7-18CA3D763166}.Debug|Any CPU.Build.0 = Debug|Any CPU + {641E0BF5-8BAA-4ECC-9EA7-18CA3D763166}.Release|Any CPU.ActiveCfg = Release|Any CPU + {641E0BF5-8BAA-4ECC-9EA7-18CA3D763166}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {5D62C437-6137-4000-A90A-6549835F593B} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} {A17406AF-E11D-421B-9913-9512BB9B3333} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} {0FD8C55D-00F5-4059-889A-D223C7D1275C} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} {515F6D6B-FB63-40F7-8173-2B94031F29B1} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} + {63DF71AF-1D31-4A4D-8127-9B8EB359889D} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} + {38556B4C-90E1-453F-8BA7-C0699577A521} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} + {641E0BF5-8BAA-4ECC-9EA7-18CA3D763166} = {16C8A8E2-B637-4A8B-828F-876523BCC79F} EndGlobalSection EndGlobal diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/Program.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/Program.cs index 06d1e8349..cc5bf0b76 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/Program.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/Program.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Convey; using Convey.Logging; @@ -13,11 +15,11 @@ using MiniSpace.Services.Posts.Application.Commands; using MiniSpace.Services.Posts.Application.Dto; using MiniSpace.Services.Posts.Application.Queries; -using MiniSpace.Services.Posts.Application.Services; using MiniSpace.Services.Posts.Infrastructure; namespace MiniSpace.Services.Posts.Api { + [ExcludeFromCodeCoverage] public class Program { public static async Task Main(string[] args) @@ -30,12 +32,6 @@ public static async Task Main(string[] args) .Build()) .Configure(app => app .UseInfrastructure() - .UseEndpoints(endpoints => endpoints - .Post("posts/search", async (cmd, ctx) => - { - var pagedResult = await ctx.RequestServices.GetService().BrowsePostsAsync(cmd); - await ctx.Response.WriteJsonAsync(pagedResult); - })) .UseDispatcherEndpoints(endpoints => endpoints .Get("", ctx => ctx.Response.WriteAsync(ctx.RequestServices.GetService().Name)) .Get("posts/{postId}") diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.docker.json b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.docker.json index 18539c4d2..07c6d2bc2 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.docker.json +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.docker.json @@ -22,9 +22,7 @@ "httpClient": { "type": "fabio", "retries": 3, - "services": { - "students": "students-service" - } + "services": {} }, "jwt": { "certificate": { diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.local.json b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.local.json index 535b691a9..29f59a9ca 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.local.json +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Api/appsettings.local.json @@ -21,11 +21,9 @@ "service": "posts-service" }, "httpClient": { - "type": "direct", + "type": "fabio", "retries": 3, - "services": { - "students": "http://localhost:5007" - }, + "services": {}, "requestMasking": { "enabled": true, "maskTemplate": "*****" diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/CreatePost.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/CreatePost.cs index fdb630f37..0291c545f 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/CreatePost.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/CreatePost.cs @@ -8,18 +8,18 @@ public class CreatePost : ICommand public Guid EventId { get; } public Guid OrganizerId { get; } public string TextContent { get; } - public IEnumerable MediaFiles { get; } + public string MediaContent { get; } public string State { get; } public DateTime? PublishDate { get; } public CreatePost(Guid postId, Guid eventId, Guid organizerId, string textContent, - IEnumerable mediaFiles, string state, DateTime? publishDate) + string mediaContent, string state, DateTime? publishDate) { - PostId = postId; + PostId = postId == Guid.Empty ? Guid.NewGuid() : postId; EventId = eventId; OrganizerId = organizerId; TextContent = textContent; - MediaFiles = mediaFiles; + MediaContent = mediaContent; State = state; PublishDate = publishDate; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/CreatePostHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/CreatePostHandler.cs index 44811ab9b..132d00a84 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/CreatePostHandler.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/CreatePostHandler.cs @@ -39,22 +39,11 @@ public async Task HandleAsync(CreatePost command, CancellationToken cancellation { throw new UnauthorizedPostCreationAttemptException(identity.Id, command.EventId); } - - if(command.PostId == Guid.Empty || await _postRepository.ExistsAsync(command.PostId)) - { - throw new InvalidPostIdException(command.PostId); - } if (!Enum.TryParse(command.State, true, out var newState)) { throw new InvalidPostStateException(command.State); } - - var mediaFiles = command.MediaFiles.ToList(); - if(mediaFiles.Count > 3) - { - throw new InvalidNumberOfPostMediaFilesException(command.PostId, mediaFiles.Count); - } switch (newState) { @@ -65,10 +54,10 @@ public async Task HandleAsync(CreatePost command, CancellationToken cancellation } var post = Post.Create(command.PostId, command.EventId, command.OrganizerId, command.TextContent, - command.MediaFiles, _dateTimeProvider.Now, newState, command.PublishDate); + command.MediaContent, _dateTimeProvider.Now, newState, command.PublishDate); await _postRepository.AddAsync(post); - await _messageBroker.PublishAsync(new PostCreated(command.PostId, post.MediaFiles)); + await _messageBroker.PublishAsync(new PostCreated(command.PostId)); } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/UpdatePostHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/UpdatePostHandler.cs index ee725ab9e..f14af1fab 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/UpdatePostHandler.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/Handlers/UpdatePostHandler.cs @@ -42,16 +42,10 @@ public async Task HandleAsync(UpdatePost command, CancellationToken cancellation throw new UnauthorizedPostOperationException(command.PostId, identity.Id); } - var mediaFiles = command.MediaFiles.ToList(); - if(mediaFiles.Count > 3) - { - throw new InvalidNumberOfPostMediaFilesException(post.Id, mediaFiles.Count); - } - - post.Update(command.TextContent, command.MediaFiles, _dateTimeProvider.Now); + post.Update(command.TextContent, command.MediaContent, _dateTimeProvider.Now); await _postRepository.UpdateAsync(post); - await _messageBroker.PublishAsync(new PostUpdated(command.PostId, post.MediaFiles)); + await _messageBroker.PublishAsync(new PostUpdated(command.PostId)); } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/SearchPosts.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/SearchPosts.cs deleted file mode 100644 index e6776a5a0..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/SearchPosts.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Convey.CQRS.Commands; -using MiniSpace.Services.Posts.Application.Dto; - -namespace MiniSpace.Services.Posts.Application.Commands -{ - public class SearchPosts : ICommand - { - public Guid StudentId { get; set; } - public PageableDto Pageable { get; set; } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/UpdatePost.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/UpdatePost.cs index e180055a3..00f6d6f40 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/UpdatePost.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Commands/UpdatePost.cs @@ -6,13 +6,13 @@ public class UpdatePost : ICommand { public Guid PostId { get; } public string TextContent { get; } - public IEnumerable MediaFiles { get; } + public string MediaContent { get; } - public UpdatePost(Guid postId, string textContent, IEnumerable mediaFiles) + public UpdatePost(Guid postId, string textContent, string mediaContent) { PostId = postId; TextContent = textContent; - MediaFiles = mediaFiles; + MediaContent = mediaContent; } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PageableDto.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PageableDto.cs deleted file mode 100644 index 9d6928419..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PageableDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Dto -{ - public class PageableDto - { - public int Page { get; set; } - public int Size { get; set; } - public SortDto Sort { get; set; } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PostDto.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PostDto.cs index 8545cc0b6..d99a1238e 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PostDto.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/PostDto.cs @@ -1,34 +1,18 @@ -using MiniSpace.Services.Posts.Core.Entities; +using System.Diagnostics.CodeAnalysis; namespace MiniSpace.Services.Posts.Application.Dto { + [ExcludeFromCodeCoverage] public class PostDto { public Guid Id { get; set; } public Guid EventId { get; set; } public Guid OrganizerId { get; set; } public string TextContent { get; set; } - public IEnumerable MediaFiles { get; set; } + public string MediaContent { get; set; } public string State { get; set; } public DateTime? PublishDate { get; set; } public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } - - public PostDto() - { - } - - public PostDto(Post post) - { - Id = post.Id; - EventId = post.EventId; - OrganizerId = post.OrganizerId; - TextContent = post.TextContent; - MediaFiles = post.MediaFiles; - State = post.State.ToString(); - PublishDate = post.PublishDate; - CreatedAt = post.CreatedAt; - UpdatedAt = post.UpdatedAt; - } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/SortDto.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/SortDto.cs deleted file mode 100644 index 0fa08bb89..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/SortDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Dto -{ - public class SortDto - { - public IEnumerable SortBy { get; set; } - public string Direction { get; set; } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/StudentEventsDto.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/StudentEventsDto.cs deleted file mode 100644 index 2f27c2fa3..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Dto/StudentEventsDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Dto -{ - public class StudentEventsDto - { - public Guid StudentId { get; set; } - public IEnumerable InterestedInEvents { get; set; } - public IEnumerable SignedUpEvents { get; set; } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/Handlers/MediaFileDeletedHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/Handlers/MediaFileDeletedHandler.cs deleted file mode 100644 index 971421190..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/Handlers/MediaFileDeletedHandler.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Convey.CQRS.Events; -using MiniSpace.Services.Posts.Application.Services; -using MiniSpace.Services.Posts.Core.Repositories; - -namespace MiniSpace.Services.Posts.Application.Events.External.Handlers -{ - public class MediaFileDeletedHandler: IEventHandler - { - private readonly IPostRepository _postRepository; - private readonly IDateTimeProvider _dateTimeProvider; - - public MediaFileDeletedHandler(IPostRepository postRepository, IDateTimeProvider dateTimeProvider) - { - _postRepository = postRepository; - _dateTimeProvider = dateTimeProvider; - } - - public async Task HandleAsync(MediaFileDeleted @event, CancellationToken cancellationToken) - { - if(@event.Source.ToLowerInvariant() != "post") - { - return; - } - - var post = await _postRepository.GetAsync(@event.SourceId); - if(post != null) - { - post.RemoveMediaFile(@event.MediaFileId, _dateTimeProvider.Now); - await _postRepository.UpdateAsync(post); - } - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/MediaFileDeleted.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/MediaFileDeleted.cs deleted file mode 100644 index f79ca8647..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/External/MediaFileDeleted.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Convey.CQRS.Events; -using Convey.MessageBrokers; - -namespace MiniSpace.Services.Posts.Application.Events.External -{ - [Message("mediafiles")] - public class MediaFileDeleted: IEvent - { - public Guid MediaFileId { get; } - public Guid SourceId { get; } - public string Source { get; } - - public MediaFileDeleted(Guid mediaFileId, Guid sourceId, string source) - { - MediaFileId = mediaFileId; - SourceId = sourceId; - Source = source; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostCreated.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostCreated.cs index bf44c36ed..6675de454 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostCreated.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostCreated.cs @@ -5,12 +5,10 @@ namespace MiniSpace.Services.Posts.Application.Events public class PostCreated : IEvent { public Guid PostId { get; } - public IEnumerable MediaFilesIds { get; } - public PostCreated(Guid postId, IEnumerable mediaFilesIds) + public PostCreated(Guid postId) { PostId = postId; - MediaFilesIds = mediaFilesIds; } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostUpdated.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostUpdated.cs index e1a6a3d95..f6471e54f 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostUpdated.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/PostUpdated.cs @@ -5,12 +5,10 @@ namespace MiniSpace.Services.Posts.Application.Events public class PostUpdated : IEvent { public Guid PostId { get; } - public IEnumerable MediaFilesIds { get; } - public PostUpdated(Guid postId, IEnumerable mediaFilesIds) + public PostUpdated(Guid postId) { PostId = postId; - MediaFilesIds = mediaFilesIds; } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/ChangePostStateRejected.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/ChangePostStateRejected.cs index 8415fb2dc..b7db43226 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/ChangePostStateRejected.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/ChangePostStateRejected.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Events; namespace MiniSpace.Services.Posts.Application.Events.Rejected { + [ExcludeFromCodeCoverage] public class ChangePostStateRejected : IRejectedEvent { public Guid PostId { get; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/CreatePostRejected.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/CreatePostRejected.cs index 6bbd8a7eb..198e1f322 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/CreatePostRejected.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/CreatePostRejected.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Events; namespace MiniSpace.Services.Posts.Application.Events.Rejected { + [ExcludeFromCodeCoverage] public class CreatePostRejected : IRejectedEvent { public Guid PostId { get; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/DeletePostRejected.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/DeletePostRejected.cs index 93c3b9c60..b4e5879f7 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/DeletePostRejected.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/DeletePostRejected.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Events; namespace MiniSpace.Services.Posts.Application.Events.Rejected { + [ExcludeFromCodeCoverage] public class DeletePostRejected : IRejectedEvent { public Guid PostId { get; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/UpdatePostRejected.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/UpdatePostRejected.cs index f3638136e..883e2d6cb 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/UpdatePostRejected.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Events/Rejected/UpdatePostRejected.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Events; namespace MiniSpace.Services.Posts.Application.Events.Rejected { + [ExcludeFromCodeCoverage] public class UpdatePostRejected : IRejectedEvent { public Guid PostId { get; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidNumberOfPostMediaFilesException.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidNumberOfPostMediaFilesException.cs deleted file mode 100644 index 481fd5d4e..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidNumberOfPostMediaFilesException.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Exceptions -{ - public class InvalidNumberOfPostMediaFilesException : AppException - { - public override string Code { get; } = "invalid_number_of_post_media_files"; - public Guid PostId { get; } - public int MediaSizeNumber { get; } - - public InvalidNumberOfPostMediaFilesException(Guid postId, int mediaFilesNumber) - : base($"Invalid media files number: {mediaFilesNumber} for post with ID: '{postId}'. It should be less or equal 3.") - { - PostId = postId; - MediaSizeNumber = mediaFilesNumber; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidPostIdException.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidPostIdException.cs deleted file mode 100644 index 13b2d64b0..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/InvalidPostIdException.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Exceptions -{ - public class InvalidPostIdException : AppException - { - public Guid PostId { get; } - - public InvalidPostIdException(Guid postId) : base($"Invalid post id: {postId}") - { - PostId = postId; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/UnauthorizedPostSearchException.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/UnauthorizedPostSearchException.cs deleted file mode 100644 index 49464f74c..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Exceptions/UnauthorizedPostSearchException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace MiniSpace.Services.Posts.Application.Exceptions -{ - public class UnauthorizedPostSearchException : AppException - { - public override string Code { get; } = "unauthorized_post_search"; - public Guid StudentId { get; } - public Guid IdentityId { get; } - - public UnauthorizedPostSearchException(Guid studentId, Guid identityId) : base("Unauthorized post search.") - { - StudentId = studentId; - IdentityId = identityId; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Extensions.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Extensions.cs index bca122302..e75cdd897 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Extensions.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Extensions.cs @@ -1,9 +1,11 @@ +using System.Diagnostics.CodeAnalysis; using Convey; using Convey.CQRS.Commands; using Convey.CQRS.Events; namespace MiniSpace.Services.Posts.Application { + [ExcludeFromCodeCoverage] public static class Extensions { public static IConveyBuilder AddApplication(this IConveyBuilder builder) diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetOrganizerPosts.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetOrganizerPosts.cs index 480b6361c..468acc48d 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetOrganizerPosts.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetOrganizerPosts.cs @@ -1,9 +1,11 @@ using System.Collections; +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Queries; using MiniSpace.Services.Posts.Application.Dto; namespace MiniSpace.Services.Posts.Application.Queries { + [ExcludeFromCodeCoverage] public class GetOrganizerPosts : IQuery> { public Guid OrganizerId { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPost.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPost.cs index 3524d49c6..fde0324d4 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPost.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPost.cs @@ -1,8 +1,10 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Queries; using MiniSpace.Services.Posts.Application.Dto; namespace MiniSpace.Services.Posts.Application.Queries { + [ExcludeFromCodeCoverage] public class GetPost : IQuery { public Guid PostId { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPosts.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPosts.cs index 1efeae6f9..a06a7d95f 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPosts.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Queries/GetPosts.cs @@ -1,8 +1,10 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Queries; using MiniSpace.Services.Posts.Application.Dto; namespace MiniSpace.Services.Posts.Application.Queries { + [ExcludeFromCodeCoverage] public class GetPosts : IQuery> { public Guid EventId { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/Clients/IStudentsServiceClient.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/Clients/IStudentsServiceClient.cs deleted file mode 100644 index 849818345..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/Clients/IStudentsServiceClient.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MiniSpace.Services.Posts.Application.Dto; - -namespace MiniSpace.Services.Posts.Application.Services.Clients -{ - public interface IStudentsServiceClient - { - Task GetAsync(Guid id); - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/IPostsService.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/IPostsService.cs deleted file mode 100644 index 6c2dc71ce..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Application/Services/IPostsService.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MiniSpace.Services.Posts.Application.Commands; -using MiniSpace.Services.Posts.Application.Dto; -using MiniSpace.Services.Posts.Core.Wrappers; - -namespace MiniSpace.Services.Posts.Application.Services -{ - public interface IPostsService - { - Task>> BrowsePostsAsync(SearchPosts command); - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Entities/Post.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Entities/Post.cs index ced44e44f..d97c788c3 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Entities/Post.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Entities/Post.cs @@ -7,20 +7,20 @@ public class Post : AggregateRoot public Guid EventId { get; private set; } public Guid OrganizerId { get; private set; } public string TextContent { get; private set; } - public IEnumerable MediaFiles { get; private set; } + public string MediaContent { get; private set; } public State State { get; private set; } public DateTime? PublishDate { get; private set; } public DateTime CreatedAt { get; private set; } public DateTime? UpdatedAt { get; private set; } - public Post(Guid id, Guid eventId, Guid organizerId, string textContent, IEnumerable mediaFiles, - DateTime createdAt, State state, DateTime? publishDate, DateTime? updatedAt = null) + public Post(Guid id, Guid eventId, Guid organizerId, string textContent, + string mediaContent, DateTime createdAt, State state, DateTime? publishDate, DateTime? updatedAt = null) { Id = id; EventId = eventId; OrganizerId = organizerId; TextContent = textContent; - MediaFiles = mediaFiles; + MediaContent = mediaContent; CreatedAt = createdAt; UpdatedAt = updatedAt; State = state; @@ -38,7 +38,7 @@ public void SetToBePublished(DateTime publishDate, DateTime now) public void SetPublished(DateTime now) { State = State.Published; - PublishDate = now; + PublishDate = null; UpdatedAt = now; } @@ -68,32 +68,22 @@ public bool UpdateState(DateTime now) } public static Post Create(AggregateId id, Guid eventId, Guid studentId, string textContent, - IEnumerable mediaFiles, DateTime createdAt, State state, DateTime? publishDate) + string mediaContent, DateTime createdAt, State state, DateTime? publishDate) { CheckTextContent(id, textContent); - return new Post(id, eventId, studentId, textContent, mediaFiles, createdAt, state, - publishDate ?? createdAt); + return new Post(id, eventId, studentId, textContent, mediaContent, createdAt, state, publishDate); } - public void Update(string textContent, IEnumerable mediaFiles, DateTime now) + public void Update(string textContent, string mediaContent, DateTime now) { CheckTextContent(Id, textContent); TextContent = textContent; - MediaFiles = mediaFiles; + MediaContent = mediaContent; UpdatedAt = now; } - public void RemoveMediaFile(Guid mediaFileId, DateTime now) - { - var mediaFile = MediaFiles.SingleOrDefault(mf => mf == mediaFileId); - if (mediaFile == Guid.Empty) - { - throw new MediaFileNotFoundException(mediaFileId, Id); - } - } - private static void CheckTextContent(AggregateId id, string textContent) { if (string.IsNullOrWhiteSpace(textContent) || textContent.Length > 5000) diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/InvalidStudentServiceClientResponseException.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/InvalidStudentServiceClientResponseException.cs deleted file mode 100644 index c76e981b4..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/InvalidStudentServiceClientResponseException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace MiniSpace.Services.Posts.Core.Exceptions -{ - public class InvalidStudentServiceClientResponseException : DomainException - { - public override string Code { get; } = "invalid_student_service_client_response"; - public Guid StudentId { get; } - - public InvalidStudentServiceClientResponseException(Guid studentId) - : base($"Invalid student service client response for student with ID: '{studentId}'.") - { - StudentId = studentId; - } - } -} diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/MediaFileNotFoundException.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/MediaFileNotFoundException.cs deleted file mode 100644 index 4a68fdb63..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Exceptions/MediaFileNotFoundException.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace MiniSpace.Services.Posts.Core.Exceptions -{ - public class MediaFileNotFoundException : DomainException - { - public override string Code { get; } = "media_file_not_found"; - public Guid MediaFileId { get; } - public Guid PostId { get; } - - public MediaFileNotFoundException(Guid mediaFileId, Guid postId) - : base($"Media file with ID: '{mediaFileId}' for post with ID: {postId} was not found.") - { - MediaFileId = mediaFileId; - PostId = postId; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Repositories/IPostRepository.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Repositories/IPostRepository.cs index f2c68e399..cb9a727d7 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Repositories/IPostRepository.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Repositories/IPostRepository.cs @@ -1,5 +1,4 @@ using MiniSpace.Services.Posts.Core.Entities; -using MiniSpace.Services.Posts.Core.Wrappers; namespace MiniSpace.Services.Posts.Core.Repositories { @@ -11,8 +10,5 @@ public interface IPostRepository Task AddAsync(Post post); Task UpdateAsync(Post post); Task DeleteAsync(Guid id); - Task ExistsAsync(Guid id); - Task<(IEnumerable posts, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseCommentsAsync(int pageNumber, int pageSize, - IEnumerable eventsIds, IEnumerable sortBy, string direction); } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/PagedResponse.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/PagedResponse.cs deleted file mode 100644 index bc82a2d4a..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/PagedResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace MiniSpace.Services.Posts.Core.Wrappers -{ - public class PagedResponse : Response - { - public int TotalPages { get; } - public int TotalElements { get; } - public int Size { get; } - public int Number { get; } - public bool First { get; } - public bool Last { get; } - public bool Empty { get; } - - public PagedResponse(T content, int pageNumber, int pageSize, int totalPages, int totalElements) - { - Content = content; - TotalPages = totalPages; - TotalElements = totalElements; - Size = pageSize; - Number = pageNumber; - First = pageNumber == 0; - Last = pageNumber == totalPages - 1; - Empty = totalElements == 0; - Succeeded = true; - Errors = null; - Message = null; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/Response.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/Response.cs deleted file mode 100644 index 2de1fbc49..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Core/Wrappers/Response.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace MiniSpace.Services.Posts.Core.Wrappers -{ - public class Response - { - public T Content { get; set; } - public bool Succeeded { get; set; } - public string[] Errors { get; set; } - public string Message { get; set; } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContext.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContext.cs index 62d23d593..958479ae4 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContext.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContext.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using MiniSpace.Services.Posts.Application; namespace MiniSpace.Services.Posts.Infrastructure.Contexts { + [ExcludeFromCodeCoverage] internal class AppContext : IAppContext { public string RequestId { get; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContextFactory.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContextFactory.cs index ac0ff8648..65b8aed07 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContextFactory.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/AppContextFactory.cs @@ -2,9 +2,11 @@ using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using MiniSpace.Services.Posts.Application; +using System.Diagnostics.CodeAnalysis; namespace MiniSpace.Services.Posts.Infrastructure.Contexts { + [ExcludeFromCodeCoverage] internal sealed class AppContextFactory : IAppContextFactory { private readonly ICorrelationContextAccessor _contextAccessor; diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/CorrelationContext.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/CorrelationContext.cs index 191f9e53d..23753504a 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/CorrelationContext.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/CorrelationContext.cs @@ -1,5 +1,8 @@ +using System.Diagnostics.CodeAnalysis; + namespace MiniSpace.Services.Posts.Infrastructure.Contexts { + [ExcludeFromCodeCoverage] internal class CorrelationContext { public string CorrelationId { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/IdentityContext.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/IdentityContext.cs index eed550c5a..9d615dc00 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/IdentityContext.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Contexts/IdentityContext.cs @@ -1,5 +1,8 @@ using MiniSpace.Services.Posts.Application; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("MiniSpace.Services.Posts.Application.UnitTests")] namespace MiniSpace.Services.Posts.Infrastructure.Contexts { internal class IdentityContext : IIdentityContext diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxCommandHandlerDecorator.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxCommandHandlerDecorator.cs index fe8411803..240cacbc4 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxCommandHandlerDecorator.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxCommandHandlerDecorator.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Commands; using Convey.MessageBrokers; using Convey.MessageBrokers.Outbox; @@ -5,6 +6,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Decorators { + [ExcludeFromCodeCoverage] [Decorator] internal sealed class OutboxCommandHandlerDecorator : ICommandHandler where TCommand : class, ICommand diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxEventHandlerDecorator.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxEventHandlerDecorator.cs index f98c19ea0..ac562b6ed 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxEventHandlerDecorator.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Decorators/OutboxEventHandlerDecorator.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Events; using Convey.MessageBrokers; using Convey.MessageBrokers.Outbox; @@ -5,6 +6,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Decorators { + [ExcludeFromCodeCoverage] [Decorator] internal sealed class OutboxEventHandlerDecorator : IEventHandler where TEvent : class, IEvent diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToMessageMapper.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToMessageMapper.cs index 21453a8b5..caa07a45b 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToMessageMapper.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToMessageMapper.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.MessageBrokers.RabbitMQ; using MiniSpace.Services.Posts.Application.Commands; using MiniSpace.Services.Posts.Application.Events.Rejected; @@ -6,6 +7,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Exceptions { + [ExcludeFromCodeCoverage] internal sealed class ExceptionToMessageMapper : IExceptionToMessageMapper { public object Map(Exception exception, object message) diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToResponseMapper.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToResponseMapper.cs index 70c051e7b..42e3230dd 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToResponseMapper.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Exceptions/ExceptionToResponseMapper.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Net; using Convey; using Convey.WebApi.Exceptions; @@ -7,6 +8,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Exceptions { + [ExcludeFromCodeCoverage] internal sealed class ExceptionToResponseMapper : IExceptionToResponseMapper { private static readonly ConcurrentDictionary Codes = new ConcurrentDictionary(); diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Extensions.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Extensions.cs index 0a91bf72a..da4d595bf 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Extensions.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Extensions.cs @@ -25,13 +25,11 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; -using MiniSpace.Services.Events.Infrastructure.Services.Clients; using Newtonsoft.Json; using MiniSpace.Services.Posts.Application; using MiniSpace.Services.Posts.Application.Commands; using MiniSpace.Services.Posts.Application.Events.External; using MiniSpace.Services.Posts.Application.Services; -using MiniSpace.Services.Posts.Application.Services.Clients; using MiniSpace.Services.Posts.Core.Repositories; using MiniSpace.Services.Posts.Infrastructure.Contexts; using MiniSpace.Services.Posts.Infrastructure.Decorators; @@ -41,9 +39,11 @@ using MiniSpace.Services.Posts.Infrastructure.Mongo.Repositories; using MiniSpace.Services.Posts.Infrastructure.Services; using MiniSpace.Services.Posts.Infrastructure.Services.Workers; +using System.Diagnostics.CodeAnalysis; namespace MiniSpace.Services.Posts.Infrastructure { + [ExcludeFromCodeCoverage] public static class Extensions { public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) @@ -54,8 +54,6 @@ public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) builder.Services.AddSingleton(); builder.Services.AddTransient(); builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddTransient(); builder.Services.AddTransient(ctx => ctx.GetRequiredService().Create()); builder.Services.TryDecorate(typeof(ICommandHandler<>), typeof(OutboxCommandHandlerDecorator<>)); builder.Services.TryDecorate(typeof(IEventHandler<>), typeof(OutboxEventHandlerDecorator<>)); diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/Extensions.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/Extensions.cs index 5e5cd3f91..a1d2c95aa 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/Extensions.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/Extensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey; using Convey.Logging.CQRS; using Microsoft.Extensions.DependencyInjection; @@ -5,6 +6,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Logging { + [ExcludeFromCodeCoverage] internal static class Extensions { public static IConveyBuilder AddHandlersLogging(this IConveyBuilder builder) diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/MessageToLogTemplateMapper.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/MessageToLogTemplateMapper.cs index f060a7f43..a3aa98da6 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/MessageToLogTemplateMapper.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Logging/MessageToLogTemplateMapper.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.Logging.CQRS; using MiniSpace.Services.Posts.Application.Commands; using MiniSpace.Services.Posts.Application.Events; @@ -5,6 +6,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Logging { + [ExcludeFromCodeCoverage] internal sealed class MessageToLogTemplateMapper : IMessageToLogTemplateMapper { private static IReadOnlyDictionary MessageTemplates diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/EventDocument.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/EventDocument.cs index 47b8b3b05..be59fb7b1 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/EventDocument.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/EventDocument.cs @@ -1,7 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using Convey.Types; namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Documents { + [ExcludeFromCodeCoverage] public class EventDocument : IIdentifiable { public Guid Id { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/Extensions.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/Extensions.cs index f02e7606b..11e99a7bc 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/Extensions.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/Extensions.cs @@ -1,13 +1,15 @@ +using System.Diagnostics.CodeAnalysis; using MiniSpace.Services.Posts.Application.Dto; using MiniSpace.Services.Posts.Core.Entities; namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Documents { + [ExcludeFromCodeCoverage] public static class Extensions { public static Post AsEntity(this PostDocument document) => new Post(document.Id, document.EventId, document.OrganizerId, document.TextContent, - document.MediaFiles, document.CreatedAt, document.State, document.PublishDate, document.UpdatedAt); + document.MediaContent, document.CreatedAt, document.State, document.PublishDate, document.UpdatedAt); public static PostDocument AsDocument(this Post entity) => new PostDocument() @@ -16,7 +18,7 @@ public static PostDocument AsDocument(this Post entity) EventId = entity.EventId, OrganizerId = entity.OrganizerId, TextContent = entity.TextContent, - MediaFiles = entity.MediaFiles, + MediaContent = entity.MediaContent, CreatedAt = entity.CreatedAt, UpdatedAt = entity.UpdatedAt, State = entity.State, @@ -30,7 +32,7 @@ public static PostDto AsDto(this PostDocument document) EventId = document.EventId, OrganizerId = document.OrganizerId, TextContent = document.TextContent, - MediaFiles = document.MediaFiles, + MediaContent = document.MediaContent, CreatedAt = document.CreatedAt, UpdatedAt = document.UpdatedAt, State = document.State.ToString().ToLowerInvariant(), diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/PostDocument.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/PostDocument.cs index 12af21c96..64fae7354 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/PostDocument.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Documents/PostDocument.cs @@ -1,15 +1,17 @@ +using System.Diagnostics.CodeAnalysis; using Convey.Types; using MiniSpace.Services.Posts.Core.Entities; namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Documents { + [ExcludeFromCodeCoverage] public class PostDocument : IIdentifiable { public Guid Id { get; set; } public Guid EventId { get; set; } public Guid OrganizerId { get; set; } public string TextContent { get; set; } - public IEnumerable MediaFiles { get; set; } + public string MediaContent { get; set; } public State State { get; set; } public DateTime? PublishDate { get; set; } public DateTime CreatedAt { get; set; } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetOrganizerPostsHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetOrganizerPostsHandler.cs index 4f84c7cb3..6ccc9cb59 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetOrganizerPostsHandler.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetOrganizerPostsHandler.cs @@ -1,4 +1,5 @@ -using Convey.CQRS.Queries; +using System.Diagnostics.CodeAnalysis; +using Convey.CQRS.Queries; using Convey.Persistence.MongoDB; using MiniSpace.Services.Posts.Application; using MiniSpace.Services.Posts.Application.Dto; @@ -9,6 +10,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Queries.Handlers { + [ExcludeFromCodeCoverage] public class GetOrganizerPostsHandler : IQueryHandler> { private readonly IMongoRepository _postRepository; diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostHandler.cs index 4a6447b53..4e88709a2 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostHandler.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostHandler.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Queries; using Convey.Persistence.MongoDB; using MiniSpace.Services.Posts.Application.Dto; @@ -6,6 +7,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Queries.Handlers { + [ExcludeFromCodeCoverage] public class GetPostHandler : IQueryHandler { private readonly IMongoRepository _repository; diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostsHandler.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostsHandler.cs index b75fa383c..38085f674 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostsHandler.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Queries/Handlers/GetPostsHandler.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.CQRS.Queries; using Convey.Persistence.MongoDB; using MiniSpace.Services.Posts.Application.Dto; @@ -9,6 +10,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Queries.Handlers { + [ExcludeFromCodeCoverage] public class GetPostsHandler : IQueryHandler> { private readonly IMongoRepository _postRepository; diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/EventMongoRepository.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/EventMongoRepository.cs index 687e76e5f..d98f1633b 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/EventMongoRepository.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/EventMongoRepository.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Convey.Persistence.MongoDB; using MiniSpace.Services.Posts.Core.Entities; using MiniSpace.Services.Posts.Core.Repositories; @@ -5,6 +6,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Repositories { + [ExcludeFromCodeCoverage] public class EventMongoRepository : IEventRepository { private readonly IMongoRepository _repository; diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/Extensions.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/Extensions.cs deleted file mode 100644 index c201f56a4..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/Extensions.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Collections; -using MiniSpace.Services.Posts.Core.Entities; -using MiniSpace.Services.Posts.Infrastructure.Mongo.Documents; -using MongoDB.Driver; - -namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Repositories -{ - public static class Extensions - { - private static readonly FilterDefinitionBuilder FilterDefinitionBuilder = Builders.Filter; - public static async Task<(int totalPages, int totalElements, IReadOnlyList data)> AggregateByPage( - this IMongoCollection collection, - FilterDefinition filterDefinition, - SortDefinition sortDefinition, - int page, - int pageSize) - { - var countFacet = AggregateFacet.Create("count", - PipelineDefinition.Create(new[] - { - PipelineStageDefinitionBuilder.Count() - })); - - var dataFacet = AggregateFacet.Create("data", - PipelineDefinition.Create(new[] - { - PipelineStageDefinitionBuilder.Sort(sortDefinition), - PipelineStageDefinitionBuilder.Skip((page - 1) * pageSize), - PipelineStageDefinitionBuilder.Limit(pageSize), - })); - - - var aggregation = await collection.Aggregate() - .Match(filterDefinition) - .Facet(countFacet, dataFacet) - .ToListAsync(); - - var count = aggregation.First() - .Facets.First(x => x.Name == "count") - .Output() - ?.FirstOrDefault() - ?.Count; - - if (count == null) - { - return (0, 0, Array.Empty()); - } - var totalPages = (int)Math.Ceiling((double)count / pageSize); - - var data = aggregation.First() - .Facets.First(x => x.Name == "data") - .Output(); - - return (totalPages, (int)count, data); - } - - public static FilterDefinition ToFilterDefinition(IEnumerable eventsIds) - { - var filterDefinition = FilterDefinitionBuilder.Empty; - - filterDefinition &= FilterDefinitionBuilder.In(p => p.EventId, eventsIds); - filterDefinition &= FilterDefinitionBuilder.Eq(p => p.State, State.Published); - - return filterDefinition; - } - - public static SortDefinition ToSortDefinition(IEnumerable sortByArguments, string direction) - { - var sort = sortByArguments.ToList(); - if(sort.Count == 0) - { - sort.Add("PublishDate"); - } - var sortDefinitionBuilder = Builders.Sort; - var sortDefinition = sort - .Select(sortBy => direction == "asc" - ? sortDefinitionBuilder.Ascending(sortBy) - : sortDefinitionBuilder.Descending(sortBy)); - var sortCombined = sortDefinitionBuilder.Combine(sortDefinition); - return sortCombined; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/PostMongoRepository.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/PostMongoRepository.cs index feb7e0619..17f9eb807 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/PostMongoRepository.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Mongo/Repositories/PostMongoRepository.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Diagnostics.CodeAnalysis; using Convey.Persistence.MongoDB; using MiniSpace.Services.Posts.Core.Entities; using MiniSpace.Services.Posts.Core.Repositories; @@ -8,6 +8,7 @@ namespace MiniSpace.Services.Posts.Infrastructure.Mongo.Repositories { + [ExcludeFromCodeCoverage] public class PostMongoRepository : IPostRepository { private readonly IMongoRepository _repository; @@ -47,33 +48,5 @@ public Task UpdateAsync(Post post) public Task DeleteAsync(Guid id) => _repository.DeleteAsync(id); - - public Task ExistsAsync(Guid id) - => _repository.ExistsAsync(p => p.Id == id); - - private async Task<(int totalPages, int totalElements, IEnumerable data)> BrowseAsync( - FilterDefinition filterDefinition, SortDefinition sortDefinition, - int pageNumber, int pageSize) - { - var pagedEvents = await _repository.Collection.AggregateByPage( - filterDefinition, - sortDefinition, - pageNumber, - pageSize); - - return pagedEvents; - } - - public async Task<(IEnumerable posts, int pageNumber,int pageSize, int totalPages, int totalElements)> BrowseCommentsAsync(int pageNumber, int pageSize, - IEnumerable eventsIds, IEnumerable sortBy, string direction) - { - var filterDefinition = Extensions.ToFilterDefinition(eventsIds); - var sortDefinition = Extensions.ToSortDefinition(sortBy, direction); - - var pagedEvents = await BrowseAsync(filterDefinition, sortDefinition, pageNumber, pageSize); - - return (pagedEvents.data.Select(e => e.AsEntity()), pageNumber, pageSize, - pagedEvents.totalPages, pagedEvents.totalElements); - } } } diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Clients/StudentsServiceClient.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Clients/StudentsServiceClient.cs deleted file mode 100644 index d58c856c5..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Clients/StudentsServiceClient.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Threading.Tasks; -using Convey.HTTP; -using MiniSpace.Services.Posts.Application.Dto; -using MiniSpace.Services.Posts.Application.Services.Clients; - -namespace MiniSpace.Services.Events.Infrastructure.Services.Clients -{ - public class StudentsServiceClient : IStudentsServiceClient - { - private readonly IHttpClient _httpClient; - private readonly string _url; - - public StudentsServiceClient(IHttpClient httpClient, HttpClientOptions options) - { - _httpClient = httpClient; - _url = options.Services["students"]; - } - - public Task GetAsync(Guid id) - => _httpClient.GetAsync($"{_url}/students/{id}/events"); - - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/MessageBroker.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/MessageBroker.cs index 83b388249..b4ed67764 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/MessageBroker.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/MessageBroker.cs @@ -6,7 +6,9 @@ using Microsoft.Extensions.Logging; using OpenTracing; using MiniSpace.Services.Posts.Application.Services; +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("MiniSpace.Services.Posts.Infrastructure.UnitTests")] namespace MiniSpace.Services.Posts.Infrastructure.Services { internal sealed class MessageBroker : IMessageBroker diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/PostsService.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/PostsService.cs deleted file mode 100644 index 1cce33758..000000000 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/PostsService.cs +++ /dev/null @@ -1,58 +0,0 @@ -using MiniSpace.Services.Posts.Application; -using MiniSpace.Services.Posts.Application.Commands; -using MiniSpace.Services.Posts.Application.Dto; -using MiniSpace.Services.Posts.Application.Exceptions; -using MiniSpace.Services.Posts.Application.Services; -using MiniSpace.Services.Posts.Application.Services.Clients; -using MiniSpace.Services.Posts.Core.Wrappers; -using MiniSpace.Services.Posts.Core.Entities; -using MiniSpace.Services.Posts.Core.Exceptions; -using MiniSpace.Services.Posts.Core.Repositories; -using MiniSpace.Services.Posts.Infrastructure.Mongo.Documents; - -namespace MiniSpace.Services.Posts.Infrastructure.Services -{ - public class PostsService : IPostsService - { - private readonly IPostRepository _postRepository; - private readonly IStudentsServiceClient _studentsServiceClient; - private readonly IAppContext _appContext; - - public PostsService(IPostRepository postRepository, IStudentsServiceClient studentsServiceClient, - IAppContext appContext) - { - _postRepository = postRepository; - _studentsServiceClient = studentsServiceClient; - _appContext = appContext; - } - - public async Task>> BrowsePostsAsync(SearchPosts command) - { - var identity = _appContext.Identity; - if (identity.IsAuthenticated && identity.Id != command.StudentId) - { - throw new UnauthorizedPostSearchException(command.StudentId, identity.Id); - } - - var studentEvents = await _studentsServiceClient.GetAsync(command.StudentId); - if (studentEvents is null) - { - throw new InvalidStudentServiceClientResponseException(command.StudentId); - } - - var eventsIds = studentEvents.InterestedInEvents.Union(studentEvents.SignedUpEvents).ToList(); - - var pageNumber = command.Pageable.Page < 1 ? 1 : command.Pageable.Page; - var pageSize = command.Pageable.Size > 10 ? 10 : command.Pageable.Size; - - var result = await _postRepository.BrowseCommentsAsync( - pageNumber, pageSize, eventsIds, command.Pageable.Sort.SortBy, command.Pageable.Sort.Direction); - - var pagedEvents = new PagedResponse>( - result.posts.Select(p => new PostDto(p)), - result.pageNumber, result.pageSize, result.totalPages, result.totalElements); - - return pagedEvents; - } - } -} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Workers/PostStateUpdaterWorker.cs b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Workers/PostStateUpdaterWorker.cs index 9ec664240..f0d0b579e 100644 --- a/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Workers/PostStateUpdaterWorker.cs +++ b/MiniSpace.Services.Posts/src/MiniSpace.Services.Posts.Infrastructure/Services/Workers/PostStateUpdaterWorker.cs @@ -11,7 +11,7 @@ public class PostStateUpdaterWorker: BackgroundService private readonly IMessageBroker _messageBroker; private readonly ICommandDispatcher _commandDispatcher; private readonly IDateTimeProvider _dateTimeProvider; - private const int MinutesInterval = 5; + public const int MinutesInterval = 5; public PostStateUpdaterWorker(IMessageBroker messageBroker, ICommandDispatcher commandDispatcher, IDateTimeProvider dateTimeProvider) diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/ChangePostStateHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/ChangePostStateHandlerTest.cs new file mode 100644 index 000000000..527b93781 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/ChangePostStateHandlerTest.cs @@ -0,0 +1,285 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; +using Microsoft.OpenApi.Extensions; +using MiniSpace.Services.Posts.Core.Exceptions; +using System.Diagnostics.Eventing.Reader; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Commands.Handlers { + public class ChangePostStateHandlerTest { + private readonly ChangePostStateHandler _changePostStateHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _dateTimeProviderMock; + private readonly Mock _messageBrokerMock; + private readonly Mock _appContextMock; + + public ChangePostStateHandlerTest() { + _postRepositoryMock = new(); + _messageBrokerMock = new(); + _dateTimeProviderMock = new(); + _appContextMock = new(); + _changePostStateHandler = new ChangePostStateHandler(_postRepositoryMock.Object, + _appContextMock.Object, + _dateTimeProviderMock.Object, + _messageBrokerMock.Object + ); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStateToBePublished_ShouldPublishAsync() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act(); + + // Assert + _messageBrokerMock.Verify(broker => broker.PublishAsync(It.IsAny()), Times.Once()); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStateToBePublished_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNullPost_ShouldThrowPostNotFoundException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync((Post)null); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonAuthenticated_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", false, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonPermittedIdentity_ShouldThrowUnauthorizedPostAccessException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "not admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsAdminAndForeignPost_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "Admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithInvalidState_ShouldThrowInvalidPostStateException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = "a"; + var eventId = Guid.NewGuid(); + + var command = new ChangePostState(postId, + state, DateTime.Today); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + State.ToBePublished, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithSameState_ShouldThrowPostStateAlreadySetException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var eventId = Guid.NewGuid(); + var state = State.Published; + + var command = new ChangePostState(postId, + state.GetDisplayName(), DateTime.Today); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithStateToBePublishedAndNullPublishDate_ShouldThrowPublishDateNullException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var eventId = Guid.NewGuid(); + var state = State.ToBePublished; + DateTime? publishDate = null; + + var command = new ChangePostState(postId, + state.GetDisplayName(), publishDate); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _changePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/CreatePostHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/CreatePostHandlerTest.cs new file mode 100644 index 000000000..640968726 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/CreatePostHandlerTest.cs @@ -0,0 +1,246 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; +using MiniSpace.Services.Posts.Core.Exceptions; +using Microsoft.OpenApi.Extensions; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Commands.Handlers { + public class CreatePostHandlerTest { + private readonly CreatePostHandler _createPostHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _eventRepositoryMock; + private readonly Mock _dateTimeProviderMock; + private readonly Mock _messageBrokerMock; + private readonly Mock _appContextMock; + + public CreatePostHandlerTest() { + _postRepositoryMock = new(); + _eventRepositoryMock = new(); + _dateTimeProviderMock = new(); + _messageBrokerMock = new(); + _appContextMock = new(); + _createPostHandler = new CreatePostHandler(_postRepositoryMock.Object, + _eventRepositoryMock.Object, + _dateTimeProviderMock.Object, + _messageBrokerMock.Object, + _appContextMock.Object); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldNotThrowException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published.GetDisplayName(); + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonAuthenticated_ShouldNotThrowException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published.GetDisplayName(); + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state, DateTime.Today); + + var isAuthenticated = false; + + var identityContext = new IdentityContext(contextId.ToString(), "", isAuthenticated, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNullEvent_ShouldThrowEventNotFoundException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var state = State.Published; + var cancelationToken = new CancellationToken(); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state.GetDisplayName(), DateTime.Today); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync((Event)null); + + // Act + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + + // Assert + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonPermittedIdentity_ShouldThrowUnauthorizedPostCreationAttemptException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, differentOrganizer, "Post", "Media Content", + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityNotRelatedToEvent_ShouldThrowUnauthorizedPostCreationAttemptException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var @event = new Event(eventId, differentOrganizer); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state.GetDisplayName(), DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithInvalidStateName_ShouldThrowInvalidPostStateException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = "a"; + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNewStateReported_ShouldThrowNotAllowedPostStateException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Reported.GetDisplayName(); + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithStateToBePublishedAndNullPublishDate_ShouldThrowPublishDateNullException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished.GetDisplayName(); + DateTime? publishDate = null; + + var @event = new Event(eventId, contextId); + var command = new CreatePost(postId, eventId, contextId, "Post", "Media Content", state, + publishDate); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync(@event); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + // Act & Assert + Func act = async () => await _createPostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/DeletePostHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/DeletePostHandlerTest.cs new file mode 100644 index 000000000..57d901ea0 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/DeletePostHandlerTest.cs @@ -0,0 +1,194 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Commands.Handlers { + public class DeletePostHandlerTest { + private readonly DeletePostHandler _deletePostHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _messageBrokerMock; + private readonly Mock _appContextMock; + + public DeletePostHandlerTest() { + _postRepositoryMock = new(); + _messageBrokerMock = new(); + _appContextMock = new(); + _deletePostHandler = new DeletePostHandler(_postRepositoryMock.Object, + _appContextMock.Object, + _messageBrokerMock.Object + ); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldNotThrowException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + + var @event = new Event(eventId, contextId); + var command = new DeletePost(postId); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNullPost_ShouldThrowPostNotFoundException() { + // Arrange + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var command = new DeletePost(postId); + + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync((Post)null); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonPermittedIdentity_ShouldThrowUnauthorizedPostAccessException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new DeletePost(postId); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "not admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsAdminAndForeignPost_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new DeletePost(postId); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "Admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsAdminAndReportedPost_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Reported; + var eventId = Guid.NewGuid(); + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new DeletePost(postId); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "Admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsNotAdminAndReportedPost_ShouldThrowUnauthorizedPostOperationException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Reported; + var eventId = Guid.NewGuid(); + + var command = new DeletePost(postId); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "not admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _deletePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostHandlerTest.cs new file mode 100644 index 000000000..88f7a12fa --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostHandlerTest.cs @@ -0,0 +1,239 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Commands.Handlers { + public class UpdatePostHandlerTest { + private readonly UpdatePostHandler _updatePostHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _dateTimeProviderMock; + private readonly Mock _messageBrokerMock; + private readonly Mock _appContextMock; + + public UpdatePostHandlerTest() { + _postRepositoryMock = new(); + _dateTimeProviderMock = new(); + _messageBrokerMock = new(); + _appContextMock = new(); + _updatePostHandler = new UpdatePostHandler(_postRepositoryMock.Object, + _appContextMock.Object, + _messageBrokerMock.Object, + _dateTimeProviderMock.Object + ); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldNotThrowException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + var textContent = "a"; + var mediaContent = "a"; + + var @event = new Event(eventId, contextId); + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldUpdateRepository() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var studentId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + var textContent = "a"; + var mediaContent = "a"; + + var @event = new Event(eventId, contextId); + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "", true, default); + + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act(); + _postRepositoryMock.Verify(repo => repo.UpdateAsync(post), Times.Once()); + } + + [Fact] + public async Task HandleAsync_WithNullPost_ShouldThrowPostNotFoundException() { + // Arrange + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var textContent = "a"; + var mediaContent = "a"; + var command = new UpdatePost(postId, textContent, mediaContent); + + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync((Post)null); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithNonPermittedIdentity_ShouldThrowUnauthorizedPostAccessException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + var textContent = "a"; + var mediaContent = "a"; + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "not admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsAdminAndForeignPost_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + var eventId = Guid.NewGuid(); + var textContent = "a"; + var mediaContent = "a"; + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "Admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsAdminAndReportedPost_ShouldNotThrowException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Reported; + var eventId = Guid.NewGuid(); + var textContent = "a"; + var mediaContent = "a"; + + Guid differentOrganizer; + do { + differentOrganizer = Guid.NewGuid(); + } while (differentOrganizer == contextId); + + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, differentOrganizer, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "Admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithIdentityAsNotAdminAndReportedPost_ShouldThrowUnauthorizedPostOperationException() { + // Arrange + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Reported; + var eventId = Guid.NewGuid(); + var textContent = "a"; + var mediaContent = "a"; + + var command = new UpdatePost(postId, textContent, mediaContent); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + var identityContext = new IdentityContext(contextId.ToString(), "not admin", true, default); + _appContextMock.Setup(ctx => ctx.Identity).Returns(identityContext); + + _postRepositoryMock.Setup(repo => repo.GetAsync(command.PostId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostHandler.HandleAsync(command, cancelationToken); + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostsStateHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostsStateHandlerTest.cs new file mode 100644 index 000000000..891006e41 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Commands/Handlers/UpdatePostsStateHandlerTest.cs @@ -0,0 +1,86 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Commands.Handlers { + public class UpdatePostsStateHandlerTest { + private readonly UpdatePostsStateHandler _updatePostStateHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _messageBrokerMock; + + public UpdatePostsStateHandlerTest() { + _postRepositoryMock = new(); + _messageBrokerMock = new(); + _updatePostStateHandler = new UpdatePostsStateHandler(_postRepositoryMock.Object, + _messageBrokerMock.Object + ); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldNotThrowException() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.Published; + + var command = new UpdatePostsState(DateTime.Today); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", DateTime.Today, + state, DateTime.Today); + + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostStateHandler.HandleAsync(command, cancelationToken); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_WithValidParametersAndStatePublished_ShouldUpdateRepository() { + // Arrange + var eventId = Guid.NewGuid(); + var contextId = Guid.NewGuid(); + var postId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var state = State.ToBePublished; + + var command = new UpdatePostsState(new DateTime(2024, 1, 1, 0, 0, 0)); + + var post = Post.Create(new AggregateId(postId), eventId, contextId, + "Text", "Media content", new DateTime(2000, 1, 1, 0, 0, 0), + state, new DateTime(2000, 1, 1, 0, 0, 0)); + + var postList = new List + { + post + }; + + _postRepositoryMock.Setup(repo => repo.GetToUpdateAsync()).ReturnsAsync(postList.AsEnumerable()); + _postRepositoryMock.Setup(repo => repo.GetAsync(postId)).ReturnsAsync(post); + + // Act & Assert + Func act = async () => await _updatePostStateHandler.HandleAsync(command, cancelationToken); + await act(); + _postRepositoryMock.Verify(repo => repo.UpdateAsync(post), Times.Once()); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventCreatedHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventCreatedHandlerTest.cs new file mode 100644 index 000000000..4880ded06 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventCreatedHandlerTest.cs @@ -0,0 +1,65 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using System.Threading; +using FluentAssertions; +using MiniSpace.Services.Posts.Application.Events.External.Handlers; +using MiniSpace.Services.Posts.Application.Events.External; +using System.ComponentModel.Design; +using Convey.CQRS.Commands; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Events.External.Handlers +{ + public class EventCreatedHandlerTest + { + private readonly EventCreatedHandler _eventDeletedHandler; + private readonly Mock _eventRepositoryMock; + + public EventCreatedHandlerTest() + { + _eventRepositoryMock = new(); + _eventDeletedHandler = new EventCreatedHandler(_eventRepositoryMock.Object); + } + + [Fact] + public async Task HandleAsync_ValidData_ShouldNotThrowExeption() + { + // Arrange + var eventId = Guid.NewGuid(); + var organizerId = Guid.NewGuid(); + var @event = new EventCreated(eventId, organizerId); + + _eventRepositoryMock.Setup(repo => repo.ExistsAsync(eventId)) + .ReturnsAsync(false); + + // Act & Assert + Func act = async () => await _eventDeletedHandler.HandleAsync(@event); + await act.Should().NotThrowAsync(); + } + + [Fact] + public async Task HandleAsync_EventAlreadyCreated_ShouldThrowEventAlreadyExistsException() + { + // Arrange + var eventId = Guid.NewGuid(); + var organizerId = Guid.NewGuid(); + var @event = new EventCreated(eventId, organizerId); + + _eventRepositoryMock.Setup(repo => repo.ExistsAsync(eventId)) + .ReturnsAsync(true); + + // Act & Assert + Func act = async () => await _eventDeletedHandler.HandleAsync(@event); + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventDeletedHandlerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventDeletedHandlerTest.cs new file mode 100644 index 000000000..d8e372e1f --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/Events/External/Handlers/EventDeletedHandlerTest.cs @@ -0,0 +1,55 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using System.Threading; +using FluentAssertions; +using MiniSpace.Services.Posts.Application.Events.External.Handlers; +using MiniSpace.Services.Posts.Application.Events.External; +using System.ComponentModel.Design; +using Convey.CQRS.Commands; + +namespace MiniSpace.Services.Posts.Application.UnitTests.Events.External.Handlers +{ + public class EventDeletedHandlerTest + { + private readonly EventDeletedHandler _eventDeletedHandler; + private readonly Mock _postRepositoryMock; + private readonly Mock _eventRepositoryMock; + private readonly Mock _commandDispatcherMock; + + public EventDeletedHandlerTest() + { + _eventRepositoryMock = new(); + _commandDispatcherMock = new(); + _postRepositoryMock = new Mock(); + _eventDeletedHandler = new EventDeletedHandler(_eventRepositoryMock.Object, + _postRepositoryMock.Object, _commandDispatcherMock.Object); + } + + [Fact] + public async Task HandleAsync_NullEvent_ShouldThrowEventNotFoundException() + { + // Arrange + var eventId = Guid.NewGuid(); + var cancelationToken = new CancellationToken(); + var @event = new EventDeleted(eventId); + + _eventRepositoryMock.Setup(repo => repo.GetAsync(eventId)).ReturnsAsync((Event)null); + + // Act + Func act = async () => await _eventDeletedHandler.HandleAsync(@event, cancelationToken); + + // Assert + await act.Should().ThrowAsync(); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/MiniSpace.Services.Posts.Application.UnitTests.csproj b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/MiniSpace.Services.Posts.Application.UnitTests.csproj new file mode 100644 index 000000000..3a7933449 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Application.UnitTests/MiniSpace.Services.Posts.Application.UnitTests.csproj @@ -0,0 +1,33 @@ + + + + net8.0 + enable + disable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/AggregatedIdTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/AggregatedIdTest.cs new file mode 100644 index 000000000..e8f4e9c27 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/AggregatedIdTest.cs @@ -0,0 +1,57 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; +using MiniSpace.Services.Posts.Core.Exceptions; +using Microsoft.AspNetCore.DataProtection.KeyManagement; + +namespace MiniSpace.Services.Posts.Core.UnitTests.Entities +{ + public class AggregatedIdTest + { + [Fact] + public void AggregateId_CreatedTwice_ShouldBeDifferent() + { + // Arrange & Act + var id1 = new AggregateId(); + var id2 = new AggregateId(); + + // Assert + Assert.NotEqual(id1.Value, id2.Value); + } + + [Fact] + public void AggregateId_CreatedTwiceSameGuid_ShouldBeSame() + { + // Arrange + var id = Guid.NewGuid(); + + // Act + var id1 = new AggregateId(id); + var id2 = new AggregateId(id); + + // Assert + Assert.Equal(id1.Value, id2.Value); + } + + [Fact] + public void AggregateId_CreateWithEmptyGuid_ShouldThrowInvalidAggregateIdException() { + Assert.Throws(() => { var id = new AggregateId(Guid.Empty); }); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/PostTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/PostTest.cs new file mode 100644 index 000000000..988c319d9 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/Entities/PostTest.cs @@ -0,0 +1,75 @@ +using Xunit; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Application.Exceptions; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Core.Entities; +using MiniSpace.Services.Posts.Core.Repositories; +using MiniSpace.Services.Posts.Application.Commands.Handlers; +using MiniSpace.Services.Posts.Application.Commands; +using MiniSpace.Services.Posts.Infrastructure.Contexts; +using Convey.CQRS.Commands; +using System.Threading; +using System.Security.Claims; +using FluentAssertions; +using MiniSpace.Services.Posts.Core.Exceptions; +using Microsoft.AspNetCore.DataProtection.KeyManagement; + +namespace MiniSpace.Services.Posts.Core.UnitTests.Entities { + public class PostTest + { + [Fact] + public void Create_WithWhitespace_ShouldThrowInvalidPostTextContentException() { + // Arrange + var id = new AggregateId(); + string textContent = " "; + + // Act & Assert + Assert.Throws(() => { + Post.Create(id, default, default, textContent, default, default, default, default); + }); + } + + [Fact] + public void Create_WithNullTextContent_ShouldThrowInvalidPostTextContentException() { + // Arrange + var id = new AggregateId(); + string textContent = null; + + // Act & Assert + Assert.Throws(() => { + Post.Create(id, default, default, textContent, default, default, default, default); + }); + } + + [Fact] + public void Create_WithTooLongTextContent_ShouldThrowInvalidPostTextContentException() { + // Arrange + var id = new AggregateId(); + string textContent = new('a', 100000); + + // Act & Assert + Assert.Throws(() => { + Post.Create(id, default, default, textContent, default, default, default, default); + }); + } + + [Fact] + public void CheckPublishDate_WithInappropriateDateTime_ShouldThrowInvalidPostPublishDateException() { + // Arrange + var id = new AggregateId(); + string textContent = new('a', 100); + var post = Post.Create(id, default, default, textContent, default, DateTime.Now, default, DateTime.Now); + + // Act & Assert + Assert.Throws(() => { + post.SetToBePublished(new DateTime(2000, 1, 1, 1, 1, 1), DateTime.Now); + }); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/MiniSpace.Services.Posts.Core.UnitTests.csproj b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/MiniSpace.Services.Posts.Core.UnitTests.csproj new file mode 100644 index 000000000..3a7933449 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Core.UnitTests/MiniSpace.Services.Posts.Core.UnitTests.csproj @@ -0,0 +1,33 @@ + + + + net8.0 + enable + disable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/MiniSpace.Services.Posts.Infrastructure.UnitTests.csproj b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/MiniSpace.Services.Posts.Infrastructure.UnitTests.csproj new file mode 100644 index 000000000..3a7933449 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/MiniSpace.Services.Posts.Infrastructure.UnitTests.csproj @@ -0,0 +1,33 @@ + + + + net8.0 + enable + disable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/MessageBrokerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/MessageBrokerTest.cs new file mode 100644 index 000000000..6c9f6d58e --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/MessageBrokerTest.cs @@ -0,0 +1,142 @@ +using Xunit; +using Moq; +using Convey.CQRS.Events; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Convey.MessageBrokers; +using Convey.MessageBrokers.Outbox; +using Convey.MessageBrokers.RabbitMQ; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using OpenTracing; +using MiniSpace.Services.Posts.Infrastructure.Services; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Application.Events; + +namespace MiniSpace.Services.Posts.Infrastructure.UnitTests.Services +{ + public class MessageBrokerTest + { + private readonly MessageBroker _messageBroker; + private readonly Mock _mockBusPublisher; + private readonly Mock _mockMessageOutbox; + private readonly Mock _mockContextAccessor; + private readonly Mock _mockHttpContextAccessor; + private readonly Mock _mockMessagePropertiesAccessor; + private readonly Mock _mockTracer; + private readonly Mock> _mockLogger; + + public MessageBrokerTest() + { + _mockBusPublisher = new Mock(); + _mockMessageOutbox = new Mock(); + _mockContextAccessor = new Mock(); + _mockHttpContextAccessor = new Mock(); + _mockMessagePropertiesAccessor = new Mock(); + _mockTracer = new Mock(); + _mockLogger = new Mock>(); + + _messageBroker = new MessageBroker(_mockBusPublisher.Object, _mockMessageOutbox.Object, _mockContextAccessor.Object, + _mockHttpContextAccessor.Object, _mockMessagePropertiesAccessor.Object, new RabbitMqOptions(), + _mockTracer.Object, _mockLogger.Object); + } + + [Fact] + public async Task PublishAsync_WithEventsAndOutboxDisabled_PublishesEvents() + { + //Arrange + var events = new List + { + new PostCreated(Guid.NewGuid()) + }; + _mockMessageOutbox.Setup(x => x.Enabled).Returns(false); + + //Act + await _messageBroker.PublishAsync(events); + + //Assert + _mockMessageOutbox.Verify( + x => x.SendAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>()), + Times.Never + ); + _mockBusPublisher.Verify( + x => x.PublishAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny>()), Times.Exactly(events.Count) + ); + } + + [Fact] + public async Task PublishAsync_WithEventsAndOutboxEnabled_SendsMessagesToOutbox() + { + //Arrange + var events = new List + { + new PostCreated(Guid.NewGuid()) + }; + _mockMessageOutbox.Setup(x => x.Enabled).Returns(true); + + //Act + await _messageBroker.PublishAsync(events); + + //Assert + _mockMessageOutbox.Verify( + x => x.SendAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>()), + Times.Exactly(events.Count) + ); + _mockBusPublisher.Verify( + x => x.PublishAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny>()), Times.Never + ); + } + + [Fact] + public async Task PublishAsync_WithoutEvents_Returns() + { + //Arrange + List events = null; + + //Act + await _messageBroker.PublishAsync(events); + + //Assert + _mockMessageOutbox.Verify( + x => x.SendAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>()), + Times.Never + ); + _mockBusPublisher.Verify( + x => x.PublishAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny>()), Times.Never + ); + } + + [Fact] + public async Task PublishAsync_WithNullEventAndOutboxDisabled_PublishesOneLessEvent() + { + //Arrange + var events = new List + { + new PostCreated(Guid.NewGuid()), + null + }; + _mockMessageOutbox.Setup(x => x.Enabled).Returns(false); + + //Act + await _messageBroker.PublishAsync(events); + + //Assert + _mockMessageOutbox.Verify( + x => x.SendAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>()), + Times.Never + ); + _mockBusPublisher.Verify( + x => x.PublishAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny>()), Times.Exactly(events.Count - 1) + ); + } + } +} \ No newline at end of file diff --git a/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/Workers/PostStateUpdaterWorkerTest.cs b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/Workers/PostStateUpdaterWorkerTest.cs new file mode 100644 index 000000000..2258332b0 --- /dev/null +++ b/MiniSpace.Services.Posts/tests/MiniSpace.Services.Posts.Infrastructure.UnitTests/Services/Workers/PostStateUpdaterWorkerTest.cs @@ -0,0 +1,95 @@ +using Xunit; +using Moq; +using Convey.CQRS.Events; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Convey.MessageBrokers; +using Convey.MessageBrokers.Outbox; +using Convey.MessageBrokers.RabbitMQ; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using OpenTracing; +using MiniSpace.Services.Posts.Infrastructure.Services; +using MiniSpace.Services.Posts.Application.Services; +using MiniSpace.Services.Posts.Application.Events; +using MiniSpace.Services.Posts.Infrastructure.Services.Workers; +using Convey.CQRS.Commands; +using Microsoft.VisualStudio.TestPlatform.Common.Utilities; +using App.Metrics.Timer; +using MiniSpace.Services.Posts.Application.Commands; + +namespace MiniSpace.Services.Posts.Infrastructure.UnitTests.Services.Workers +{ + public class PostStateUpdaterWorkerTest + { + private readonly PostStateUpdaterWorker _postStateUpdaterWorker; + private readonly Mock _messageBrokerMock; + private readonly Mock _commandDispatcherMock; + private readonly Mock _dateTimeProviderMock; + + public PostStateUpdaterWorkerTest() + { + _messageBrokerMock = new Mock(); + _commandDispatcherMock = new Mock(); + _dateTimeProviderMock = new Mock(); + _postStateUpdaterWorker = new PostStateUpdaterWorker(_messageBrokerMock.Object, + _commandDispatcherMock.Object, _dateTimeProviderMock.Object); + } + + [Fact] + public async Task ExecuteAsync_WithDefaultParameters_ShouldPublishStarted() + { + // Arrange + CancellationToken cancellationToken = new CancellationToken(); + + // Act + await _postStateUpdaterWorker.StartAsync(cancellationToken); + await Task.Delay(1000); + + // Assert + _messageBrokerMock.Verify(broker => + broker.PublishAsync(It.IsAny()), + Times.Once()); + } + + [Fact] + public async Task ExecuteAsync_WithCancelRequested_ShouldPublishStopped() + { + // Arrange + CancellationToken cancellationToken = new CancellationToken(); + + // Act + await _postStateUpdaterWorker.StartAsync(cancellationToken); + await Task.Delay(1000); + await _postStateUpdaterWorker.StopAsync(cancellationToken); + + // Assert + _messageBrokerMock.Verify(broker => + broker.PublishAsync(It.IsAny()), + Times.Once()); + } + + [Fact] + public async Task ExecuteAsync_WithTimeSetToInvokeCommandDispatcherSendAsync_ShouldCommandDispatcherSendAsync() + { + CancellationToken cancellationToken = new CancellationToken(); + var nowMock0 = new DateTime(2024, 5, 26, 18, PostStateUpdaterWorker.MinutesInterval * 1, 0); + var nowMock1 = new DateTime(2024, 5, 26, 18, PostStateUpdaterWorker.MinutesInterval * 2, 0); + + _dateTimeProviderMock.Setup(prov => prov.Now).Returns(nowMock0); + await _postStateUpdaterWorker.StartAsync(cancellationToken); + await Task.Delay(1000); + await _postStateUpdaterWorker.StopAsync(cancellationToken); + + _dateTimeProviderMock.Setup(prov => prov.Now).Returns(nowMock1); + await _postStateUpdaterWorker.StartAsync(cancellationToken); + await Task.Delay(1000); + await _postStateUpdaterWorker.StopAsync(cancellationToken); + + _commandDispatcherMock.Verify(broker => + broker.SendAsync(It.IsAny(), It.IsAny()), + Times.Exactly(2)); + } + } +} \ No newline at end of file