From 7a8a933fd63f7c456f625bd1885ad429d1fc0832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20J=C3=B8rgen=20Skogstad?= Date: Mon, 9 Sep 2024 10:15:05 +0200 Subject: [PATCH] fix(webapi): Return 422 when existing transmission IDs are used in dialog update (#1094) ## Description Regression(?), or missed bug from when transmissions where introduced. * Added missing return when finding existing IDs * Adjusted the log message for existing activities to use the same extension method as transmissions * Added tests for both existing activities and existing transmissions ## Related Issue(s) - #1088 ## Verification - [ ] **Your** code builds clean without any errors or warnings - [ ] Manual testing done (required) - [ ] Relevant automated test added (if you find this hard, leave it and we'll help out) ## Documentation - [ ] Documentation is updated (either in `docs`-directory, Altinnpedia or a separate linked PR in [altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if applicable) --- .../Commands/Update/UpdateDialogCommand.cs | 5 +- .../DialogGenerator.cs | 17 +++++ .../Dialogs/Commands/UpdateDialogTests.cs | 69 +++++++++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogCommand.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogCommand.cs index 7ac9ca025..5d7430510 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogCommand.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogCommand.cs @@ -183,9 +183,7 @@ private async Task AppendActivity(DialogEntity dialog, UpdateDialogDto dto, Canc var existingIds = await _db.GetExistingIds(newDialogActivities, cancellationToken); if (existingIds.Count != 0) { - _domainContext.AddError( - nameof(UpdateDialogDto.Activities), - $"Entity '{nameof(DialogActivity)}' with the following key(s) already exists: ({string.Join(", ", existingIds)})."); + _domainContext.AddError(DomainFailure.EntityExists(existingIds)); return; } @@ -257,6 +255,7 @@ private async Task AppendTransmission(DialogEntity dialog, UpdateDialogDto dto, if (existingIds.Count != 0) { _domainContext.AddError(DomainFailure.EntityExists(existingIds)); + return; } dialog.Transmissions.AddRange(newDialogTransmissions); diff --git a/src/Digdir.Tool.Dialogporten.GenerateFakeData/DialogGenerator.cs b/src/Digdir.Tool.Dialogporten.GenerateFakeData/DialogGenerator.cs index 68072281e..15ffde70e 100644 --- a/src/Digdir.Tool.Dialogporten.GenerateFakeData/DialogGenerator.cs +++ b/src/Digdir.Tool.Dialogporten.GenerateFakeData/DialogGenerator.cs @@ -7,6 +7,7 @@ using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities; using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions; using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities; +using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions; using Digdir.Domain.Dialogporten.Domain.Http; using Medo; @@ -227,6 +228,22 @@ private static int CalculateControlDigit(string input, int[] weights) public static CreateDialogDialogActivityDto GenerateFakeDialogActivity(DialogActivityType.Values? type = null) => GenerateFakeDialogActivities(1, type)[0]; + public static List GenerateFakeDialogTransmissions(int? count = null, + DialogTransmissionType.Values? type = null) + { + return new Faker() + .RuleFor(o => o.Id, _ => Uuid7.NewUuid7().ToGuid(true)) + .RuleFor(o => o.CreatedAt, f => f.Date.Past()) + .RuleFor(o => o.Type, f => type ?? f.PickRandom()) + .RuleFor(o => o.Sender, _ => new() { ActorType = ActorType.Values.ServiceOwner }) + .RuleFor(o => o.Content, _ => new() + { + Title = new() { Value = GenerateFakeLocalizations(1) }, + Summary = new() { Value = GenerateFakeLocalizations(3) } + }) + .Generate(count ?? new Randomizer().Number(1, 4)); + } + public static List GenerateFakeDialogActivities(int? count = null, DialogActivityType.Values? type = null) { return new Faker() diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/UpdateDialogTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/UpdateDialogTests.cs index c1dafe4bd..167555250 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/UpdateDialogTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Features/V1/ServiceOwner/Dialogs/Commands/UpdateDialogTests.cs @@ -4,6 +4,7 @@ using Digdir.Domain.Dialogporten.Application.Integration.Tests.Common; using Digdir.Domain.Dialogporten.Domain.Actors; using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities; +using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions; using Digdir.Tool.Dialogporten.GenerateFakeData; using FluentAssertions; @@ -42,6 +43,74 @@ public async Task New_Activity_Should_Be_Able_To_Refer_To_Old_Activity() result.Should().NotBeNull(); } + [Fact] + public async Task Cannot_Include_Old_Activities_To_UpdateCommand() + { + // Arrange + var (_, createCommandResponse) = await GenerateDialogWithActivity(); + var getDialogQuery = new GetDialogQuery { DialogId = createCommandResponse.AsT0.Value }; + var getDialogDto = await Application.Send(getDialogQuery); + + var mapper = Application.GetMapper(); + var updateDialogDto = mapper.Map(getDialogDto.AsT0); + + // Ref. old activity + updateDialogDto.Activities.Add(new UpdateDialogDialogActivityDto + { + Id = getDialogDto.AsT0.Activities.First().Id, + Type = DialogActivityType.Values.DialogCreated, + PerformedBy = new UpdateDialogDialogActivityPerformedByActorDto + { + ActorType = ActorType.Values.ServiceOwner + } + }); + + // Act + var updateResponse = await Application.Send(new UpdateDialogCommand { Id = createCommandResponse.AsT0.Value, Dto = updateDialogDto }); + + // Assert + updateResponse.TryPickT5(out var domainError, out _).Should().BeTrue(); + domainError.Should().NotBeNull(); + domainError.Errors.Should().Contain(e => e.ErrorMessage.Contains("already exists")); + } + + [Fact] + public async Task Cannot_Include_Old_Transmissions_In_UpdateCommand() + { + // Arrange + var createDialogCommand = DialogGenerator.GenerateSimpleFakeDialog(); + var existingTransmission = DialogGenerator.GenerateFakeDialogTransmissions(count: 1).First(); + createDialogCommand.Transmissions.Add(existingTransmission); + var createCommandResponse = await Application.Send(createDialogCommand); + + var getDialogQuery = new GetDialogQuery { DialogId = createCommandResponse.AsT0.Value }; + var getDialogDto = await Application.Send(getDialogQuery); + + var mapper = Application.GetMapper(); + var updateDialogDto = mapper.Map(getDialogDto.AsT0); + + // Ref. old transmission + updateDialogDto.Transmissions.Add(new UpdateDialogDialogTransmissionDto + { + Id = existingTransmission.Id, + Type = DialogTransmissionType.Values.Information, + Sender = new() { ActorType = ActorType.Values.ServiceOwner }, + Content = new() + { + Title = new() { Value = DialogGenerator.GenerateFakeLocalizations(3) }, + Summary = new() { Value = DialogGenerator.GenerateFakeLocalizations(3) } + } + }); + + // Act + var updateResponse = await Application.Send(new UpdateDialogCommand { Id = createCommandResponse.AsT0.Value, Dto = updateDialogDto }); + + // Assert + updateResponse.TryPickT5(out var domainError, out _).Should().BeTrue(); + domainError.Should().NotBeNull(); + domainError.Errors.Should().Contain(e => e.ErrorMessage.Contains("already exists")); + } + private async Task<(CreateDialogCommand, CreateDialogResult)> GenerateDialogWithActivity() { var createDialogCommand = DialogGenerator.GenerateSimpleFakeDialog();