Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for ActionController using IInstanceDataMutator #900

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/Altinn.App.Api/Controllers/ActionsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
[ProducesResponseType(409)]
[ProducesResponseType(500)]
[ProducesResponseType(401)]
public async Task<ActionResult<UserActionResponse>> Perform(

Check warning on line 78 in src/Altinn.App.Api/Controllers/ActionsController.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

ModelState.IsValid should be checked in controller actions. (https://rules.sonarsource.com/csharp/RSPEC-6967)
[FromRoute] string org,
[FromRoute] string app,
[FromRoute] int instanceOwnerPartyId,
Expand Down Expand Up @@ -213,10 +213,9 @@
);
await saveTask;

var updatedDataModels = changes.FormDataChanges.ToDictionary(
c => c.DataElementIdentifier.Id,
c => c.CurrentFormData
);
var updatedDataModels = changes
.FormDataChanges.Where(c => c.Type != ChangeType.Deleted)
.ToDictionary(c => c.DataElementIdentifier.Id, c => c.CurrentFormData);

return Ok(
new UserActionResponse()
Expand All @@ -242,7 +241,7 @@
{
var taskId =
dataAccessor.Instance.Process?.CurrentTask?.ElementId
?? throw new Exception("Unable to validate instance without a started process.");

Check warning on line 244 in src/Altinn.App.Api/Controllers/ActionsController.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

'System.Exception' should not be thrown by user code. (https://rules.sonarsource.com/csharp/RSPEC-112)
var validationIssues = await _validationService.ValidateIncrementalFormData(
dataAccessor,
taskId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
if (modelType.FullName != classRef)
{
throw new InvalidOperationException(
$"Data object registered for {dataTypeId} is not of type {classRef} as specified in application metadata"
$"Tried to save {modelType.FullName} as {dataTypeId}, but applicationmetadata.json specifies {classRef}"
);
}

Expand Down Expand Up @@ -587,14 +587,14 @@
var changes = GetDataElementChanges(initializeAltinnRowId: false);
if (changes.AllChanges.Count != previousChanges.AllChanges.Count)
{
throw new Exception("Number of data elements have changed by validators");

Check warning on line 590 in src/Altinn.App.Core/Internal/Data/InstanceDataUnitOfWork.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

'System.Exception' should not be thrown by user code. (https://rules.sonarsource.com/csharp/RSPEC-112)
}

foreach (var previousChange in previousChanges.AllChanges)
{
var currentChange =
changes.AllChanges.FirstOrDefault(c => c.DataElement?.Id == previousChange.DataElement?.Id)
?? throw new Exception("Number of data elements have changed by validators");

Check warning on line 597 in src/Altinn.App.Core/Internal/Data/InstanceDataUnitOfWork.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

'System.Exception' should not be thrown by user code. (https://rules.sonarsource.com/csharp/RSPEC-112)

var equal = (currentChange, previousChange) switch
{
Expand All @@ -605,11 +605,11 @@
=> currentSpan.SequenceEqual(previousSpan),
(BinaryDataChange current, BinaryDataChange previous)
=> current.CurrentBinaryData.Span.SequenceEqual(previous.CurrentBinaryData.Span),
_ => throw new Exception("Data element type has changed by validators")

Check warning on line 608 in src/Altinn.App.Core/Internal/Data/InstanceDataUnitOfWork.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

'System.Exception' should not be thrown by user code. (https://rules.sonarsource.com/csharp/RSPEC-112)
};
if (!equal)
{
throw new Exception(

Check warning on line 612 in src/Altinn.App.Core/Internal/Data/InstanceDataUnitOfWork.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

'System.Exception' should not be thrown by user code. (https://rules.sonarsource.com/csharp/RSPEC-112)
$"Data element {previousChange.DataType.Id} with id {previousChange.DataElement?.Id} has been changed by validators"
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Altinn.App.Core/Models/UserAction/UserActionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
/// <param name="buttonId">The id of the button that triggered the action (optional)</param>
/// <param name="actionMetadata"></param>
/// <param name="language">The currently used language by the user (or null if not available)</param>
[Obsolete("Use the constructor with IInstanceDataAccessor instead")]

Check warning on line 43 in src/Altinn.App.Core/Models/UserAction/UserActionContext.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Do not forget to remove this deprecated code someday. (https://rules.sonarsource.com/csharp/RSPEC-1133)
public UserActionContext(
Instance instance,
int? userId,
Expand All @@ -50,7 +50,7 @@
)
{
Instance = instance;
// ! TODO: Deprecated constructor, remove in v9

Check warning on line 53 in src/Altinn.App.Core/Models/UserAction/UserActionContext.cs

View workflow job for this annotation

GitHub Actions / Static code analysis

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
DataMutator = null!;
UserId = userId;
ButtonId = buttonId;
Expand All @@ -66,7 +66,7 @@
/// <summary>
/// Access dataElements through this accessor to ensure that changes gets saved in storage and returned to frontend
/// </summary>
public IInstanceDataAccessor DataMutator { get; }
public IInstanceDataMutator DataMutator { get; }

/// <summary>
/// The user performing the action
Expand Down
289 changes: 277 additions & 12 deletions test/Altinn.App.Api.Tests/Controllers/ActionsControllerTests.cs

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions test/Altinn.App.Api.Tests/Controllers/DataControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public async Task PutDataElement_MissingDataType_ReturnsBadRequest()
string token = PrincipalUtil.GetOrgToken("nav", "160694123");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

TestData.DeleteInstanceAndData(org, app, instanceOwnerPartyId, guid);
TestData.PrepareInstance(org, app, instanceOwnerPartyId, guid);

using var content = new StringContent("{}", System.Text.Encoding.UTF8, "application/json"); // empty valid json
Expand All @@ -53,7 +52,6 @@ public async Task PostBinaryElement_ContentTooLarge_ReturnsBadRequest()
string token = PrincipalUtil.GetOrgToken("nav", "160694123");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

TestData.DeleteInstanceAndData(org, app, instanceOwnerPartyId, guid);
TestData.PrepareInstance(org, app, instanceOwnerPartyId, guid);

using var content = new ByteArrayContent(new byte[1024 * 1024 + 1]); // 1 mb
Expand Down Expand Up @@ -93,7 +91,6 @@ public async Task CreateDataElement_BinaryPdf_AnalyserShouldRunOk()
HttpClient client = GetRootedClient(org, app);

Guid guid = new Guid("0fc98a23-fe31-4ef5-8fb9-dd3f479354cd");
TestData.DeleteInstanceAndData(org, app, 1337, guid);
TestData.PrepareInstance(org, app, 1337, guid);

// Setup the request
Expand Down Expand Up @@ -127,7 +124,6 @@ public async Task CreateDataElement_ZeroBytes_BinaryPdf_AnalyserShouldReturnBadR
HttpClient client = GetRootedClient(org, app);

Guid guid = new Guid("0fc98a23-fe31-4ef5-8fb9-dd3f479354cd");
TestData.DeleteInstanceAndData(org, app, 1337, guid);
TestData.PrepareInstance(org, app, 1337, guid);

// Setup the request
Expand Down Expand Up @@ -163,7 +159,6 @@ public async Task CreateDataElement_JpgFakedAsPdf_AnalyserShouldRunAndFail()
HttpClient client = GetRootedClient(org, app);

Guid guid = new Guid("1fc98a23-fe31-4ef5-8fb9-dd3f479354ce");
TestData.DeleteInstanceAndData(org, app, 1337, guid);
TestData.PrepareInstance(org, app, 1337, guid);

// Setup the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public async Task PutDataElement_LegacyLayoutEvaluatorState_ReturnsOk()
Guid dataGuid = Guid.Parse("f3e04c65-aa70-40ec-84df-087cc2583402");
HttpClient client = GetRootedClient(org, app, 1337, instanceOwnerPartyId);

TestData.DeleteInstanceAndData(org, app, instanceOwnerPartyId, instanceGuid);
TestData.PrepareInstance(org, app, instanceOwnerPartyId, instanceGuid);

// Update data element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ public DataControllerPatchTests(WebApplicationFactory<Program> factory, ITestOut
services.AddSingleton(_dataProcessorMock.Object);
services.AddSingleton(_formDataValidatorMock.Object);
};
TestData.DeleteInstanceAndData(Org, App, InstanceOwnerPartyId, _instanceGuid);
TestData.PrepareInstance(Org, App, InstanceOwnerPartyId, _instanceGuid);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public class DataController_PostTests : ApiTestBase, IClassFixture<WebApplicatio
public DataController_PostTests(WebApplicationFactory<Program> factory, ITestOutputHelper outputHelper)
: base(factory, outputHelper)
{
TestData.DeleteInstanceAndData(_org, _app, _instanceOwnerPartyId, _instanceGuid);
TestData.PrepareInstance(_org, _app, _instanceOwnerPartyId, _instanceGuid);
OverrideServicesForAllTests = (services) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public ProcessControllerTests(WebApplicationFactory<Program> factory, ITestOutpu
services.AddSingleton(_dataProcessorMock.Object);
services.AddSingleton(_formDataValidatorMock.Object);
};
TestData.DeleteInstanceAndData(Org, App, InstanceOwnerPartyId, _instanceGuid);
TestData.PrepareInstance(Org, App, InstanceOwnerPartyId, _instanceGuid);
}

Expand All @@ -74,7 +73,6 @@ public async Task Get_ShouldReturnProcessTasks()

HttpClient client = GetRootedClient(org, app, 1337, partyId, 3);

TestData.DeleteInstanceAndData(org, app, partyId, instanceId);
TestData.PrepareInstance(org, app, partyId, instanceId);

string url = $"/{org}/{app}/instances/{partyId}/{instanceId}/process";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ ITestOutputHelper outputHelper
services.AddSingleton(_dataProcessorMock.Object);
services.AddSingleton(_formDataValidatorMock.Object);
};
TestData.DeleteInstanceAndData(Org, App, InstanceOwnerPartyId, InstanceGuid);
TestData.PrepareInstance(Org, App, InstanceOwnerPartyId, InstanceGuid);
}

Expand Down
10 changes: 6 additions & 4 deletions test/Altinn.App.Api.Tests/CustomWebApplicationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ private void ConfigureFakeHttpClientHandler(IServiceCollection services)
}

/// <summary>
/// Set this in your test class constructor
/// Helper to quickly verify the status code and deserialize the content of a response.
/// and print the content to output helper
/// </summary>
protected async Task<T> VerifyStatusAndDeserialize<T>(
HttpResponseMessage response,
Expand All @@ -224,7 +225,10 @@ HttpStatusCode expectedStatusCode
{
// Deserialize content and log everything if it fails
var content = await response.Content.ReadAsStringAsync();
OutputHelper.WriteLine($"Response content: {content}");
OutputHelper.WriteLine(
$"{response.RequestMessage?.Method} {response.RequestMessage?.RequestUri?.PathAndQuery}"
);
OutputHelper.WriteLine(JsonUtils.IndentJson(content));
// Verify status code
response.Should().HaveStatusCode(expectedStatusCode);
try
Expand All @@ -239,8 +243,6 @@ HttpStatusCode expectedStatusCode
OutputHelper.WriteLine(
$"Failed to deserialize content of {response.RequestMessage?.Method} request to {response.RequestMessage?.RequestUri} as {ReflectionUtils.GetTypeNameWithGenericArguments<T>()}:"
);

OutputHelper.WriteLine(JsonUtils.IndentJson(content));
OutputHelper.WriteLine(string.Empty);
throw;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ignore guid.json files
????????-????-????-????-????????????.json
# ignore copied blobs
*/*/*/blob/????????-????-????-????-????????????
**/blob/????????-????-????-????-????????????
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,5 @@
"isSoftDeleted": false,
"isHardDeleted": false,
"readStatus": "Read"
},
"data": [
{
"id": "de288942-a8af-4f77-a1f1-6e1ede1cd502",
"dataType": "default",
"contentType": "application/xml",
"size": 0,
"locked": false
}
]
}
}
15 changes: 14 additions & 1 deletion test/Altinn.App.Api.Tests/Data/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ Guid dataGuid
return Path.Combine(dataDirectory, $"{dataGuid}.json");
}

public static string GetDataElementBlobContnet(
string org,
string app,
int instanceOwnerId,
Guid instanceGuid,
Guid dataGuid
)
{
string dataElementPath = GetDataBlobPath(org, app, instanceOwnerId, instanceGuid, dataGuid);
return File.ReadAllText(dataElementPath);
}

public static string GetDataBlobPath(string org, string app, int instanceOwnerId, Guid instanceGuid, Guid dataGuid)
{
string dataDirectory = GetDataDirectory(org, app, instanceOwnerId, instanceGuid);
Expand Down Expand Up @@ -142,6 +154,7 @@ public static string GetInstancePath(string org, string app, int instanceOwnerId

public static void PrepareInstance(string org, string app, int instanceOwnerId, Guid instanceGuid)
{
DeleteInstanceAndData(org, app, instanceOwnerId, instanceGuid);
string instancePath = GetInstancePath(org, app, instanceOwnerId, instanceGuid);

string preInstancePath = instancePath.Replace(".json", ".pretest.json");
Expand Down Expand Up @@ -185,7 +198,7 @@ public static void DeleteInstanceAndData(string org, string app, int instanceOwn
}
}

public static void DeleteDataForInstance(string org, string app, int instanceOwnerId, Guid instanceGuid)
private static void DeleteDataForInstance(string org, string app, int instanceOwnerId, Guid instanceGuid)
{
string path = GetDataDirectory(org, app, instanceOwnerId, instanceGuid);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "ttd/task-action",
"org": "ttd",
"id": "tdd/task-action",
"org": "tdd",
"title": {
"nb": "task-action"
},
Expand All @@ -25,7 +25,7 @@
],
"appLogic": {
"autoCreate": true,
"classRef": "Altinn.App.Models.Scheme",
"classRef": "Altinn.App.Api.Tests.Data.apps.tdd.task_action.config.models.Scheme",
"allowAnonymousOnStateless": false,
"autoDeleteOnProcessEnd": false
},
Expand All @@ -50,4 +50,4 @@
"createdBy": "tjololo",
"lastChanged": "2023-05-31T08:03:25.9385925Z",
"lastChangedBy": "tjololo"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma warning disable IDE1006 // Naming Styles
namespace Altinn.App.Api.Tests.Data.apps.tdd.task_action.config.models;

/// <summary>
/// Class for the model
/// </summary>
public class Scheme
{
public string? name { get; set; }

public string? description { get; set; }

public string? TestCustomButtonInput { get; set; }

public string? TestCustomButtonReadOnlyInput { get; set; }
}

#pragma warning restore IDE1006 // Naming Styles
Loading