Skip to content

Commit

Permalink
Merge branch 'main' into feat/1804-pdf-preview
Browse files Browse the repository at this point in the history
  • Loading branch information
adamhaeger authored Nov 15, 2024
2 parents 48bb118 + 48c652c commit 6080c68
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/Altinn.App.Api/Controllers/InstancesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -905,9 +905,9 @@ int instanceOwnerPartyId

private void ConditionallySetReadStatus(Instance instance)
{
string? orgClaimValue = User.GetOrg();
var isInstantiatedByOrg = User.GetOrg() is not null;

if (orgClaimValue == instance.Org)
if (isInstantiatedByOrg)
{
// Default value for ReadStatus is "not read"
return;
Expand Down
4 changes: 2 additions & 2 deletions src/Altinn.App.Core/Internal/Data/InstanceDataUnitOfWork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public void RemoveDataElement(DataElementIdentifier dataElementIdentifier)
DataType = dataType,
FileName = dataElement.Filename,
ContentType = dataElement.ContentType,
CurrentBinaryData = default,
CurrentBinaryData = ReadOnlyMemory<byte>.Empty,
}
);
}
Expand All @@ -250,7 +250,7 @@ public void RemoveDataElement(DataElementIdentifier dataElementIdentifier)
? cfd
: _modelSerializationService.GetEmpty(dataType),
PreviousFormData = _modelSerializationService.GetEmpty(dataType),
CurrentBinaryData = null,
CurrentBinaryData = ReadOnlyMemory<byte>.Empty,
PreviousBinaryData = _binaryCache.TryGetCachedValue(dataElementIdentifier, out var value)
? value
: null,
Expand Down
11 changes: 9 additions & 2 deletions src/Altinn.App.Core/Models/DataElementChanges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,15 @@ public sealed class FormDataChange : DataElementChange
/// The binary representation (for storage) of the data element after changes
/// </summary>
/// <remarks>
/// Not available for form data in data processing phase, because it can't reflect
/// the changes made by the data processors.
/// This is null during data processing, because the deserialized data
/// is still valid for editing, and the binary data can't keep up with the
/// changes
///
/// Availible during validation, because then the data should not be
/// changed, and it is used for storing and for verification that validators
/// does not mutate the data.
///
/// For deleted data elements this is set to <see cref="ReadOnlyMemory{T}.Empty"/>
/// </remarks>
public required ReadOnlyMemory<byte>? CurrentBinaryData { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public EnumSerializationTests(WebApplicationFactory<Program> factory, ITestOutpu
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddScoped(_ => _authorizationClientMock.Object);
services.AddScoped(_ => _appMetadataMock.Object);
services.AddSingleton(_authorizationClientMock.Object);
services.AddSingleton(_appMetadataMock.Object);
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
TestId: Guid_2
},
{
url.path: /tdd/contributer-restriction/instances/500600/0fc98a23-fe31-4ef5-8fb9-dd3f479354cd/data/fc121812-0336-45fb-a75c-490df3ad5109
url.path: /tdd/contributer-restriction/instances/500600/0fc98a23-fe31-4ef5-8fb9-dd3f479354ce/data/fc121812-0336-45fb-a75c-490df3ad5109
},
{
url.scheme: http
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
Expand All @@ -12,6 +13,7 @@
using Altinn.App.Common.Tests;
using Altinn.App.Core.Features;
using Altinn.App.Core.Internal.Language;
using Altinn.App.Core.Models;
using Altinn.App.Core.Models.Validation;
using Altinn.Platform.Storage.Interface.Models;
using App.IntegrationTests.Mocks.Services;
Expand All @@ -22,6 +24,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Moq;
using Xunit.Abstractions;

Expand All @@ -43,9 +46,10 @@ public class DataControllerPatchTests : ApiTestBase, IClassFixture<WebApplicatio
private const string App = "contributer-restriction";
private const int UserId = 1337;
private const int InstanceOwnerPartyId = 500600;
private static readonly Guid _instanceGuid = new("0fc98a23-fe31-4ef5-8fb9-dd3f479354cd");
private static readonly Guid _instanceGuid = new("0fc98a23-fe31-4ef5-8fb9-dd3f479354ce");
private static readonly string _instanceId = $"{InstanceOwnerPartyId}/{_instanceGuid}";
private static readonly Guid _dataGuid = new("fc121812-0336-45fb-a75c-490df3ad5109");
private static readonly Guid _binaryDataGuid = new("fc121812-0336-45fb-a75c-490df3ad510a");

// Define mocks
private readonly Mock<IDataProcessor> _dataProcessorMock = new(MockBehavior.Strict);
Expand Down Expand Up @@ -1013,6 +1017,99 @@ public async Task IgnoredValidators_NotExecuted()
_formDataValidatorMock.Verify();
}

[Fact]
public async Task RunPatch_DeleteElementInDataProcessor_ReturnsUpdatedInstance()
{
var dataWriteProcessorMock = new Mock<IDataWriteProcessor>(MockBehavior.Strict);

dataWriteProcessorMock
.Setup(d =>
d.ProcessDataWrite(It.IsAny<IInstanceDataMutator>(), "Task_1", It.IsAny<DataElementChanges>(), null)
)
.Returns(
(IInstanceDataMutator dataMutator, string taskId, DataElementChanges changes, string? language) =>
{
dataMutator.RemoveDataElement(new DataElementIdentifier(_dataGuid));
dataMutator.RemoveDataElement(new DataElementIdentifier(_binaryDataGuid));
return Task.CompletedTask;
}
)
.Verifiable(Times.Once);

OverrideServicesForThisTest = services =>
{
services.RemoveAll<IDataProcessor>();
services.AddSingleton(dataWriteProcessorMock.Object);
};

var patch = new DataPatchRequestMultiple()
{
IgnoredValidators = [],
Patches =
[
// new DataPatchRequestMultiple.PatchListItem(_dataGuid,
// new JsonPatch(PatchOperation.Replace(path, JsonNode.Parse("\"Ola Olsen\""))))
]
};

var (_, _, parsedResponse) = await CallPatchMultipleApi<DataPatchResponseMultiple>(patch, HttpStatusCode.OK);

parsedResponse.Instance.Data.Should().BeEmpty();
}

[Fact]
public async Task RunPatch_MutateDataInValidator_Errors()
{
OverrideEnvironment = "Development";
OverrideServicesForThisTest = services =>
{
services.RemoveAll<IDataProcessor>();
};
_formDataValidatorMock.SetupGet(fdv => fdv.DataType).Returns("default");
_formDataValidatorMock
.Setup(fdv => fdv.HasRelevantChanges(It.IsAny<object>(), It.IsAny<object>()))
.Returns(true);
_formDataValidatorMock
.Setup(v => v.ValidateFormData(It.IsAny<Instance>(), It.IsAny<DataElement>(), It.IsAny<object>(), "nb"))
.ReturnsAsync(
(Instance _instanceGuid, DataElement dataElement, object data, string? language) =>
{
if (data is Skjema skjema)
{
skjema.Melding ??= new();
skjema.Melding.Name = "InvalidChangeInValidator";
}
return new List<ValidationIssue>();
}
)
.Verifiable(Times.Once);

var path = JsonPointer.Create("melding", "name");
var patch = new DataPatchRequestMultiple()
{
IgnoredValidators = [],
Patches =
[
new DataPatchRequestMultiple.PatchListItem(
_dataGuid,
new JsonPatch(PatchOperation.Test(path, JsonNode.Parse("null")))
)
]
};

var url = $"/{Org}/{App}/instances/{_instanceId}/data?language=nb";

var action = async () =>
{
using var updateDataElementContent = JsonContent.Create(patch);
await GetClient().PatchAsync(url, updateDataElementContent);
};
// Not sure why the exception propagates out of the api call in WebApplicationFactory.
(await action.Should().ThrowAsync<Exception>())
.Which.Message.Should()
.Contain("changed by validators");
}

~DataControllerPatchTests()
{
_client?.Dispose();
Expand Down
19 changes: 18 additions & 1 deletion test/Altinn.App.Api.Tests/CustomWebApplicationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Moq;
using OpenTelemetry;
Expand All @@ -32,6 +34,7 @@ public class ApiTestBase
};

protected readonly ITestOutputHelper OutputHelper;
protected string? OverrideEnvironment { get; set; }
private readonly WebApplicationFactory<Program> _factory;

protected IServiceProvider Services { get; private set; }
Expand All @@ -50,7 +53,7 @@ public class ApiTestBase
return false;
};

public ApiTestBase(WebApplicationFactory<Program> factory, ITestOutputHelper outputHelper)
protected ApiTestBase(WebApplicationFactory<Program> factory, ITestOutputHelper outputHelper)
{
_factory = factory;
Services = _factory.Services;
Expand Down Expand Up @@ -128,6 +131,20 @@ public HttpClient GetRootedClient(string org, string app, bool includeTraceConte
builder.ConfigureTestServices(services => OverrideServicesForAllTests(services));
builder.ConfigureTestServices(OverrideServicesForThisTest);
builder.ConfigureTestServices(ConfigureFakeHttpClientHandler);
// Mock IHostEnvironment to return the environment name we want to test
if (OverrideEnvironment is not null)
{
builder.ConfigureTestServices(services =>
{
var hostEnvironmentMock = new Mock<IHostEnvironment>(MockBehavior.Strict);
hostEnvironmentMock.SetupGet(e => e.EnvironmentName).Returns(() => OverrideEnvironment);
hostEnvironmentMock.SetupGet(e => e.ApplicationName).Returns("Altinn.App.Api");
hostEnvironmentMock.SetupGet(e => e.ContentRootPath).Returns(appRootPath);
services.Replace(ServiceDescriptor.Singleton(hostEnvironmentMock.Object));
});
}
});
var services = Services = factory.Services;
_ = services.GetService<TelemetrySink>(); // The sink starts listening when it is constructed, so we make sure to construct here
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "500600/0fc98a23-fe31-4ef5-8fb9-dd3f479354cd",
"id": "500600/0fc98a23-fe31-4ef5-8fb9-dd3f479354ce",
"instanceOwner": {
"partyId": "500600",
"organisationNumber": "897069631"
Expand Down Expand Up @@ -27,4 +27,4 @@
"isHardDeleted": false,
"readStatus": "Read"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Lat som at dette er en pdf fil
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "fc121812-0336-45fb-a75c-490df3ad5109",
"instanceGuid": "0fc98a23-fe31-4ef5-8fb9-dd3f479354cd",
"instanceGuid": "0fc98a23-fe31-4ef5-8fb9-dd3f479354ce",
"dataType": "default",
"filename": null,
"contentType": "application/xml",
Expand All @@ -19,4 +19,4 @@
"createdBy": null,
"lastChanged": "2024-01-10T22:04:31.511965Z",
"lastChangedBy": null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"id": "fc121812-0336-45fb-a75c-490df3ad510a",
"instanceGuid": "0fc98a23-fe31-4ef5-8fb9-dd3f479354ce",
"dataType": "customElement",
"filename": "test.pdf",
"contentType": "application/pdf",
"blobStoragePath": null,
"selfLinks": null,
"size": 0,
"contentHash": null,
"locked": false,
"refs": null,
"isRead": true,
"tags": [],
"deleteStatus": null,
"fileScanResult": "NotApplicable",
"references": null,
"created": null,
"createdBy": null,
"lastChanged": "2024-01-10T22:04:31.511965Z",
"lastChangedBy": null
}
9 changes: 8 additions & 1 deletion test/Altinn.App.Api.Tests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@
{
ApplicationName = "Altinn.App.Api.Tests",
WebRootPath = Path.Join(TestData.GetTestDataRootDirectory(), "apps", "tdd", "contributer-restriction"),
EnvironmentName = "Production",
EnvironmentName = "Production"
}
);
builder.WebHost.UseDefaultServiceProvider(
(context, options) =>
{
options.ValidateScopes = true; // Allways validate scopes in test
options.ValidateOnBuild = true;
}
);

Expand Down

0 comments on commit 6080c68

Please sign in to comment.