diff --git a/backend/packagegroups/NuGet.props b/backend/packagegroups/NuGet.props
index 1007d47fed8..4801794327b 100644
--- a/backend/packagegroups/NuGet.props
+++ b/backend/packagegroups/NuGet.props
@@ -21,7 +21,6 @@
-
@@ -42,6 +41,15 @@
+
+
+
+
+
+
+
+
+
@@ -56,13 +64,13 @@
-
-
+
+
-
+
diff --git a/backend/src/DataModeling/Converter/Csharp/CsharpGenerationException.cs b/backend/src/DataModeling/Converter/Csharp/CsharpGenerationException.cs
index 76a606468e8..b66bbe00ca8 100644
--- a/backend/src/DataModeling/Converter/Csharp/CsharpGenerationException.cs
+++ b/backend/src/DataModeling/Converter/Csharp/CsharpGenerationException.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.Serialization;
namespace Altinn.Studio.DataModeling.Converter.Csharp
{
@@ -23,11 +22,5 @@ public CsharpGenerationException(string message) : base(message)
public CsharpGenerationException(string message, Exception innerException) : base(message, innerException)
{
}
-
- ///
- protected CsharpGenerationException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
-
}
}
diff --git a/backend/src/DataModeling/Converter/Json/JsonSchemaConvertException.cs b/backend/src/DataModeling/Converter/Json/JsonSchemaConvertException.cs
index b1d300ec7c6..3619f7f8748 100644
--- a/backend/src/DataModeling/Converter/Json/JsonSchemaConvertException.cs
+++ b/backend/src/DataModeling/Converter/Json/JsonSchemaConvertException.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.Serialization;
namespace Altinn.Studio.DataModeling.Converter.Json
{
@@ -29,12 +28,5 @@ public JsonSchemaConvertException(string message) : base(message)
public JsonSchemaConvertException(string message, Exception innerException) : base(message, innerException)
{
}
-
- ///
- ///
- ///
- protected JsonSchemaConvertException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/backend/src/DataModeling/Converter/Metadata/ModelMetadataConvertException.cs b/backend/src/DataModeling/Converter/Metadata/ModelMetadataConvertException.cs
index e5f89193706..73846a7081f 100644
--- a/backend/src/DataModeling/Converter/Metadata/ModelMetadataConvertException.cs
+++ b/backend/src/DataModeling/Converter/Metadata/ModelMetadataConvertException.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.Serialization;
namespace Altinn.Studio.DataModeling.Converter.Metadata
{
@@ -23,10 +22,5 @@ public MetamodelConvertException(string message) : base(message)
public MetamodelConvertException(string message, Exception innerException) : base(message, innerException)
{
}
-
- ///
- protected MetamodelConvertException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/backend/src/DataModeling/Converter/Xml/XmlSchemaConvertException.cs b/backend/src/DataModeling/Converter/Xml/XmlSchemaConvertException.cs
index 8111ef93a6f..f785fafdca3 100644
--- a/backend/src/DataModeling/Converter/Xml/XmlSchemaConvertException.cs
+++ b/backend/src/DataModeling/Converter/Xml/XmlSchemaConvertException.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.Serialization;
namespace Altinn.Studio.DataModeling.Converter.Xml
{
@@ -29,12 +28,5 @@ public XmlSchemaConvertException(string message) : base(message)
public XmlSchemaConvertException(string message, Exception innerException) : base(message, innerException)
{
}
-
- ///
- ///
- ///
- protected XmlSchemaConvertException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/backend/src/DataModeling/DataModeling.csproj b/backend/src/DataModeling/DataModeling.csproj
index dce74b39402..4f91a5245f7 100644
--- a/backend/src/DataModeling/DataModeling.csproj
+++ b/backend/src/DataModeling/DataModeling.csproj
@@ -4,6 +4,7 @@
Altinn.Studio.DataModeling
latest
Altinn.Studio.DataModeling
+ 1.0.0
diff --git a/backend/src/Designer/Controllers/ApplicationMetadataController.cs b/backend/src/Designer/Controllers/ApplicationMetadataController.cs
index 53fb28f44c9..f5d54343721 100644
--- a/backend/src/Designer/Controllers/ApplicationMetadataController.cs
+++ b/backend/src/Designer/Controllers/ApplicationMetadataController.cs
@@ -23,7 +23,6 @@ public class ApplicationMetadataController : ControllerBase
/// Initializes a new instance of the class.
///
/// The application metadata service
- /// The user requests synchronization service
public ApplicationMetadataController(IApplicationMetadataService applicationMetadataService)
{
_applicationMetadataService = applicationMetadataService;
diff --git a/backend/src/Designer/Controllers/DatamodelsController.cs b/backend/src/Designer/Controllers/DatamodelsController.cs
index f7c57a88525..12e8874da6d 100644
--- a/backend/src/Designer/Controllers/DatamodelsController.cs
+++ b/backend/src/Designer/Controllers/DatamodelsController.cs
@@ -6,6 +6,7 @@
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Altinn.Studio.DataModeling.Validator.Json;
using Altinn.Studio.Designer.Filters;
using Altinn.Studio.Designer.Helpers;
@@ -37,6 +38,7 @@ public class DatamodelsController : ControllerBase
///
/// Interface for working with models.
/// An .
+ /// Interface for validating that the model name does not already belong to a data type
public DatamodelsController(ISchemaModelService schemaModelService, IJsonSchemaValidator jsonSchemaValidator, IModelNameValidator modelNameValidator)
{
_schemaModelService = schemaModelService;
@@ -248,6 +250,34 @@ public async Task UseXsdFromRepo(string org, string repository, s
}
}
+ ///
+ /// Gets the dataType for a given data model.
+ ///
+ [HttpGet("datamodel/{modelName}/dataType")]
+ [UseSystemTextJson]
+ public async Task> GetModelDataType(string org, string repository, string modelName)
+ {
+ DataType dataType = await _schemaModelService.GetModelDataType(org, repository, modelName);
+ return Ok(dataType);
+ }
+
+ ///
+ /// Updates the dataType for a given data model.
+ ///
+ [HttpPut("datamodel/{modelName}/dataType")]
+ [UseSystemTextJson]
+ public async Task SetModelDataType(string org, string repository, string modelName, [FromBody] DataType dataType)
+ {
+ if (!Equals(modelName, dataType.Id))
+ {
+ return BadRequest("Model name in path and request body does not match");
+ }
+
+ await _schemaModelService.SetModelDataType(org, repository, modelName, dataType);
+ DataType updatedDataType = await _schemaModelService.GetModelDataType(org, repository, modelName);
+ return Ok(updatedDataType);
+ }
+
private static string GetFileNameFromUploadedFile(IFormFile thefile)
{
return ContentDispositionHeaderValue.Parse(new StringSegment(thefile.ContentDisposition)).FileName.ToString();
diff --git a/backend/src/Designer/Controllers/OptionsController.cs b/backend/src/Designer/Controllers/OptionsController.cs
index 97b4baf1c60..56f23452ce0 100644
--- a/backend/src/Designer/Controllers/OptionsController.cs
+++ b/backend/src/Designer/Controllers/OptionsController.cs
@@ -129,6 +129,25 @@ public async Task>> GetOptionsList(string org, string
}
}
+ ///
+ /// Gets all usages of all optionListIds in the layouts as .
+ ///
+ /// Unique identifier of the organisation responsible for the app.
+ /// Application identifier which is unique within an organisation.
+ /// A that observes if operation is cancelled.
+ [HttpGet]
+ [Produces("application/json")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [Route("usage")]
+ public async Task>> GetOptionListsReferences(string org, string repo, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
+
+ List optionListReferences = await _optionsService.GetAllOptionListReferences(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer), cancellationToken);
+ return Ok(optionListReferences);
+ }
+
///
/// Creates or overwrites an options list.
///
diff --git a/backend/src/Designer/Controllers/Preview/DataController.cs b/backend/src/Designer/Controllers/Preview/DataController.cs
index d4515b42cf9..dc3e03def6a 100644
--- a/backend/src/Designer/Controllers/Preview/DataController.cs
+++ b/backend/src/Designer/Controllers/Preview/DataController.cs
@@ -1,50 +1,101 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Nodes;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web;
using Altinn.Platform.Storage.Interface.Models;
using Altinn.Studio.Designer.Filters;
using Altinn.Studio.Designer.Helpers;
-using Altinn.Studio.Designer.Models;
+using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models.Preview;
-using Altinn.Studio.Designer.Services.Implementation;
using Altinn.Studio.Designer.Services.Interfaces;
using Altinn.Studio.Designer.Services.Interfaces.Preview;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Routing;
namespace Altinn.Studio.Designer.Controllers.Preview
{
[Authorize]
[AutoValidateAntiforgeryToken]
[Route("{org:regex(^(?!designer))}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/instances/{partyId}/{instanceGuid}/data")]
- public class DataController(IHttpContextAccessor httpContextAccessor,
- IPreviewService previewService,
- ISchemaModelService schemaModelService,
- IDataService dataService
+ public class DataController(
+ IInstanceService instanceService,
+ IDataService dataService,
+ IAltinnGitRepositoryFactory altinnGitRepositoryFactory
+
) : Controller
{
+ //
+ // Redirect requests from older versions of Studio to old controller
+ //
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ string org = context.RouteData.Values["org"] as string;
+ string app = context.RouteData.Values["app"] as string;
+ string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
+ AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
+ if (!altinnAppGitRepository.AppUsesLayoutSets())
+ {
+ RouteValueDictionary routeData = context.RouteData.Values;
+ foreach (var queryParam in context.HttpContext.Request.Query)
+ {
+ routeData[queryParam.Key] = queryParam.Value.ToString();
+ }
+ context.Result = base.RedirectToActionPreserveMethod(controllerName: "OldData", routeValues: routeData);
+ }
+ base.OnActionExecuting(context);
+ }
+
[HttpGet("{dataGuid}")]
- public ActionResult Get([FromRoute] Guid dataGuid)
+ [UseSystemTextJson]
+ public ActionResult Get(
+ [FromRoute] Guid dataGuid
+ )
{
JsonNode dataItem = dataService.GetDataElement(dataGuid);
return Ok(dataItem);
}
[HttpPost]
- public ActionResult Post(
+ [UseSystemTextJson]
+ public ActionResult Post(
[FromRoute] int partyId,
[FromRoute] Guid instanceGuid,
[FromQuery] string dataType
)
{
DataElement dataElement = dataService.CreateDataElement(partyId, instanceGuid, dataType);
+ instanceService.AddDataElement(instanceGuid, dataElement);
return Created("link-to-app-placeholder", dataElement);
}
+ [HttpPatch]
+ [UseSystemTextJson]
+ public ActionResult PatchMultiple(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ [FromBody] DataPatchRequestMultiple dataPatch
+ )
+ {
+ Instance instance = instanceService.GetInstance(instanceGuid);
+
+ List newDataModels = [];
+ dataPatch.Patches.ForEach(patch =>
+ {
+ JsonNode dataItem = dataService.PatchDataElement(patch.DataElementId, patch.Patch);
+ newDataModels.Add(new DataModelPairResponse(patch.DataElementId, dataItem));
+ });
+
+ return Ok(new DataPatchResponseMultiple()
+ {
+ ValidationIssues = [],
+ NewDataModels = newDataModels,
+ Instance = instance,
+ });
+ }
+
[HttpPatch("{dataGuid}")]
[UseSystemTextJson]
public ActionResult Patch(
@@ -60,72 +111,30 @@ [FromBody] DataPatchRequest dataPatch
});
}
- [HttpDelete("{dataTypeId}")]
- public ActionResult DeleteAttachment([FromRoute] Guid dataGuid)
+ [HttpDelete("{dataGuid}")]
+ public ActionResult Delete(
+ [FromRoute] Guid instanceGuid,
+ [FromRoute] Guid dataGuid
+ )
{
+ instanceService.RemoveDataElement(instanceGuid, dataGuid);
return Ok();
}
[HttpGet("{dataGuid}/validate")]
- public ActionResult ValidateInstanceForData([FromRoute] Guid dataGuid)
+ public ActionResult ValidateInstanceForData(
+ [FromRoute] Guid dataGuid
+ )
{
return Ok(new List());
}
- [HttpPost("{dataTypeId}/tags")]
- public ActionResult UpdateTagsForAttachment([FromBody] string tag)
- {
- return Created("link-to-app-placeholder", tag);
- }
-
- [HttpGet(PreviewService.MockDataTaskId)]
- public async Task GetDefaultFormData(
- [FromRoute] string org,
- [FromRoute] string app,
- [FromRoute] int partyId,
- CancellationToken cancellationToken
+ [HttpPost("{dataGuid}/tags")]
+ public ActionResult UpdateTagsForAttachment(
+ [FromBody] string tag
)
{
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- string refererHeader = Request.Headers.Referer;
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- DataType dataType = await previewService.GetDataTypeForLayoutSetName(org, app, developer, layoutSetName, cancellationToken);
- // For apps that does not have a datamodel
- if (dataType == null)
- {
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, partyId, layoutSetName, cancellationToken);
- return Ok(mockInstance.Id);
- }
- string modelPath = $"/App/models/{dataType.Id}.schema.json";
- string decodedPath = Uri.UnescapeDataString(modelPath);
- string formData = await schemaModelService.GetSchema(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer), decodedPath, cancellationToken);
- return Ok(formData);
- }
-
- [HttpPut(PreviewService.MockDataTaskId)]
- public async Task UpdateFormData(
- [FromRoute] string org,
- [FromRoute] string app,
- [FromRoute] int partyId,
- CancellationToken cancellationToken
- )
- {
- return await GetDefaultFormData(org, app, partyId, cancellationToken);
- }
-
- [HttpPatch(PreviewService.MockDataTaskId)]
- public ActionResult PatchFormData()
- {
- return Ok();
- }
-
- private static string GetSelectedLayoutSetInEditorFromRefererHeader(string refererHeader)
- {
- Uri refererUri = new(refererHeader);
- string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
-
- return string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ return Created("link-to-app-placeholder", tag);
}
}
}
-
diff --git a/backend/src/Designer/Controllers/Preview/InstancesController.cs b/backend/src/Designer/Controllers/Preview/InstancesController.cs
index 12bfaa02504..ba947d1bea7 100644
--- a/backend/src/Designer/Controllers/Preview/InstancesController.cs
+++ b/backend/src/Designer/Controllers/Preview/InstancesController.cs
@@ -2,203 +2,231 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using System.Web;
using Altinn.App.Core.Internal.Process.Elements;
using Altinn.Platform.Storage.Interface.Models;
+using Altinn.Studio.Designer.Filters;
using Altinn.Studio.Designer.Helpers;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
+using Altinn.Studio.Designer.Models.App;
using Altinn.Studio.Designer.Services.Interfaces;
+using Altinn.Studio.Designer.Services.Interfaces.Preview;
using LibGit2Sharp;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Routing;
-namespace Altinn.Studio.Designer.Controllers.Preview
+namespace Altinn.Studio.Designer.Controllers.Preview;
+
+[Authorize]
+[AutoValidateAntiforgeryToken]
+[Route("{org:regex(^(?!designer))}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/instances")]
+public class InstancesController(IHttpContextAccessor httpContextAccessor,
+ IPreviewService previewService,
+ IAltinnGitRepositoryFactory altinnGitRepositoryFactory,
+ IInstanceService instanceService,
+ IApplicationMetadataService applicationMetadataService
+) : Controller
{
- [Authorize]
- [AutoValidateAntiforgeryToken]
- [Route("{org:regex(^(?!designer))}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/instances")]
- public class InstancesController(IHttpContextAccessor httpContextAccessor,
- IPreviewService previewService,
- IAltinnGitRepositoryFactory altinnGitRepositoryFactory
- ) : Controller
+ //
+ // Redirect requests from older versions of Studio to old controller
+ //
+ public override void OnActionExecuting(ActionExecutingContext context)
{
- ///
- /// Action for creating the mocked instance object
- ///
- /// Unique identifier of the organisation responsible for the app.
- /// Application identifier which is unique within an organisation.
- ///
- /// A that observes if operation is cancelled.
- /// The mocked instance object
- [HttpPost]
- public async Task> Instances(string org, string app, [FromQuery] int? instanceOwnerPartyId, CancellationToken cancellationToken)
+ string org = context.RouteData.Values["org"] as string;
+ string app = context.RouteData.Values["app"] as string;
+ string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
+ AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
+ if (!altinnAppGitRepository.AppUsesLayoutSets())
{
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- string refererHeader = Request.Headers["Referer"];
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, instanceOwnerPartyId, layoutSetName, cancellationToken);
- return Ok(mockInstance);
+ RouteValueDictionary routeData = context.RouteData.Values;
+ foreach (var queryParam in context.HttpContext.Request.Query)
+ {
+ routeData[queryParam.Key] = queryParam.Value.ToString();
+ }
+ context.Result = base.RedirectToActionPreserveMethod(controllerName: "OldInstances", routeValues: routeData);
}
+ base.OnActionExecuting(context);
+ }
- ///
- /// Action for getting a mocked response for the current task connected to the instance
- ///
- /// The processState
- [HttpGet("{partyId}/{instanceGuId}/process")]
- public async Task> Process(string org, string app, [FromRoute] int partyId, CancellationToken cancellationToken)
- {
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- string refererHeader = Request.Headers["Referer"];
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, partyId, layoutSetName, cancellationToken);
- List tasks = await previewService.GetTasksForAllLayoutSets(org, app, developer, cancellationToken);
- AppProcessState processState = new AppProcessState(mockInstance.Process)
- {
- ProcessTasks = tasks != null
- ? new List(tasks?.ConvertAll(task => new AppProcessTaskTypeInfo { ElementId = task, AltinnTaskType = "data" }))
- : null
- };
+ ///
+ /// Get instance data
+ ///
+ [HttpGet("{partyId}/{instanceGuid}")]
+ [UseSystemTextJson]
+ public ActionResult GetInstance(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken)
+ {
+ Instance instanceData = instanceService.GetInstance(instanceGuid);
+ return Ok(instanceData);
+ }
- return Ok(processState);
- }
+ ///
+ /// Create a new instance
+ ///
+ [HttpPost]
+ public async Task> Post(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromQuery] int instanceOwnerPartyId,
+ [FromQuery] string taskId,
+ [FromQuery] string language = null
+ )
+ {
+ ApplicationMetadata applicationMetadata = await applicationMetadataService.GetApplicationMetadataFromRepository(org, app);
+ Instance instance = instanceService.CreateInstance(org, app, instanceOwnerPartyId, taskId, applicationMetadata.DataTypes);
+ return Ok(instance);
+ }
- ///
- /// Endpoint to get instance for next process step
- ///
- /// A mocked instance object
- [HttpGet("{partyId}/{instanceGuId}")]
- public async Task> InstanceForNextTask(string org, string app, [FromRoute] int partyId, CancellationToken cancellationToken)
- {
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- string refererHeader = Request.Headers["Referer"];
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, partyId, layoutSetName, cancellationToken);
- return Ok(mockInstance);
- }
+ ///
+ /// Endpoint to get active instances for apps with state/layout sets/multiple processes
+ ///
+ /// A list of a single mocked instance
+ [HttpGet("{partyId}/active")]
+ public ActionResult> ActiveInstances(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId
+ )
+ {
+ // Simulate never having any active instances
+ List activeInstances = new();
+ return Ok(activeInstances);
+ }
- ///
- /// Endpoint to get active instances for apps with state/layout sets/multiple processes
- ///
- /// A list of a single mocked instance
- [HttpGet("{partyId}/active")]
- public ActionResult> ActiveInstancesForAppsWithLayoutSets(string org, string app, [FromRoute] int partyId)
- {
- // Simulate never having any active instances
- List activeInstances = new();
- return Ok(activeInstances);
- }
+ ///
+ /// Endpoint to validate an instance
+ ///
+ /// Ok
+ [HttpGet("{partyId}/{instanceGuId}/validate")]
+ public ActionResult ValidateInstance()
+ {
+ return Ok();
+ }
- ///
- /// Endpoint to validate an instance
- ///
- /// Ok
- [HttpGet("{partyId}/{instanceGuId}/validate")]
- public ActionResult ValidateInstance()
+ ///
+ /// Action for getting a mocked response for the current task connected to the instance
+ ///
+ /// The processState
+ [HttpGet("{partyId}/{instanceGuid}/process")]
+ public async Task> Process(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken)
+ {
+ string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
+ Instance instance = instanceService.GetInstance(instanceGuid);
+ List tasks = await previewService.GetTasksForAllLayoutSets(org, app, developer, cancellationToken);
+ AppProcessState processState = new(instance.Process)
{
- return Ok();
- }
+ ProcessTasks = tasks != null
+ ? new List(tasks?.ConvertAll(task => new AppProcessTaskTypeInfo { ElementId = task, AltinnTaskType = "data" }))
+ : null
+ };
- ///
- /// Action for getting a mocked response for the next task connected to the instance
- ///
- /// The processState object on the global mockInstance object
- [HttpGet("{partyId}/{instanceGuId}/process/next")]
- public async Task ProcessNext(string org, string app, [FromRoute] int partyId, CancellationToken cancellationToken)
- {
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- string refererHeader = Request.Headers["Referer"];
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, partyId, layoutSetName, cancellationToken);
- return Ok(mockInstance.Process);
- }
+ return Ok(processState);
+ }
- ///
- /// Action for mocking an end to the process in order to get receipt after "send inn" is pressed
- ///
- /// Process object where ended is set
- [HttpPut("{partyId}/{instanceGuId}/process/next")]
- public async Task UpdateProcessNext(string org, string app, [FromRoute] int partyId, [FromQuery] string lang, CancellationToken cancellationToken)
- {
- string refererHeader = Request.Headers["Referer"];
- string layoutSetName = GetSelectedLayoutSetInEditorFromRefererHeader(refererHeader);
- if (string.IsNullOrEmpty(layoutSetName))
- {
- string endProcess = """{"ended": "ended"}""";
- return Ok(endProcess);
- }
- string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
- Instance mockInstance = await previewService.GetMockInstance(org, app, developer, partyId, layoutSetName, cancellationToken);
- return Ok(mockInstance.Process);
- }
+ ///
+ /// Action for getting a mocked response for the next task connected to the instance
+ ///
+ /// The processState object on the global mockInstance object
+ [HttpGet("{partyId}/{instanceGuid}/process/next")]
+ public ActionResult ProcessNext(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken
+ )
+ {
+ Instance instance = instanceService.GetInstance(instanceGuid);
+ return Ok(instance.Process);
+ }
- ///
- /// Action for getting options list for a given options list id for a given instance
- ///
- /// Unique identifier of the organisation responsible for the app.
- /// Application identifier which is unique within an organisation.
- /// The id of the options list
- /// The language for the options list
- /// The source of the options list
- /// A that observes if operation is cancelled.
- /// The options list if it exists, otherwise nothing
- [HttpGet("{partyId}/{instanceGuid}/options/{optionListId}")]
- public async Task> GetOptionsForInstance(string org, string app, string optionListId, [FromQuery] string language, [FromQuery] string source, CancellationToken cancellationToken)
- {
- try
- {
- // TODO: Need code to get dynamic options list based on language and source?
- string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
- AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
- string options = await altinnAppGitRepository.GetOptionsList(optionListId, cancellationToken);
- return Ok(options);
- }
- catch (NotFoundException)
- {
- // Return empty list since app-frontend don't handle a null result
- return Ok(new List());
- }
- }
+ ///
+ /// Action for mocking an end to the process in order to get receipt after "send inn" is pressed
+ ///
+ /// Process object where ended is set
+ [HttpPut("{partyId}/{instanceGuid}/process/next")]
+ public ActionResult UpdateProcessNext(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ [FromQuery] string lang,
+ CancellationToken cancellationToken
+ )
+ {
+ Instance instance = instanceService.GetInstance(instanceGuid);
+ return Ok(instance.Process);
+ }
- ///
- /// Action for getting data list for a given data list id for a given instance
- ///
- /// Unique identifier of the organisation responsible for the app.
- /// Application identifier which is unique within an organisation.
- /// The id of the data list
- /// The language for the data list
- /// The number of items to return
- /// A that observes if operation is cancelled.
- /// The options list if it exists, otherwise nothing
- [HttpGet("{partyId}/{instanceGuid}/datalists/{dataListId}")]
- public ActionResult> GetDataListsForInstance(string org, string app, string dataListId, [FromQuery] string language, [FromQuery] string size, CancellationToken cancellationToken)
+ ///
+ /// Action for getting options list for a given options list id for a given instance
+ ///
+ [HttpGet("{partyId}/{instanceGuid}/options/{optionListId}")]
+ public async Task> GetOptionsForInstance(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] string optionListId,
+ [FromQuery] string language,
+ [FromQuery] string source,
+ CancellationToken cancellationToken
+ )
+ {
+ try
{
- // TODO: Should look into whether we can get some actual data here, or if we can make an "informed" mock based on the setup.
- // For now, we just return an empty list.
- return Ok(new List());
+ // TODO: Need code to get dynamic options list based on language and source?
+ string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
+ AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
+ string options = await altinnAppGitRepository.GetOptionsList(optionListId, cancellationToken);
+ return Ok(options);
}
-
- ///
- /// Action for updating data model with tag for attachment component // TODO: Figure out what actually happens here
- ///
- /// Unique identifier of the organisation responsible for the app.
- /// Application identifier which is unique within an organisation.
- /// Current page in running app
- /// Current layout set in running app
- /// Connected datatype for that process task
- /// The options list if it exists, otherwise nothing
- [HttpPost("{partyId}/{instanceGuid}/pages/order")]
- public IActionResult UpdateAttachmentWithTag(string org, string app, [FromQuery] string currentPage, [FromQuery] string layoutSetId, [FromQuery] string dataTypeId)
+ catch (NotFoundException)
{
- return Ok();
+ // Return empty list since app-frontend don't handle a null result
+ return Ok(new List());
}
+ }
- private static string GetSelectedLayoutSetInEditorFromRefererHeader(string refererHeader)
- {
- Uri refererUri = new(refererHeader);
- string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ ///
+ /// Action for getting data list for a given data list id for a given instance
+ ///
+ [HttpGet("{partyId}/{instanceGuid}/datalists/{dataListId}")]
+ public ActionResult> GetDataListsForInstance(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] string dataListId,
+ [FromQuery] string language,
+ [FromQuery] string size,
+ CancellationToken cancellationToken
+ )
+ {
+ // TODO: Should look into whether we can get some actual data here, or if we can make an "informed" mock based on the setup.
+ // For now, we just return an empty list.
+ return Ok(new List());
+ }
- return string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
- }
+ ///
+ /// Action for updating data model with tag for attachment component // TODO: Figure out what actually happens here
+ ///
+ [HttpPost("{partyId}/{instanceGuid}/pages/order")]
+ public IActionResult UpdateAttachmentWithTag(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromQuery] string currentPage,
+ [FromQuery] string layoutSetId,
+ [FromQuery] string dataTypeId
+ )
+ {
+ return Ok();
}
}
diff --git a/backend/src/Designer/Controllers/Preview/V3/OldDataController.cs b/backend/src/Designer/Controllers/Preview/V3/OldDataController.cs
new file mode 100644
index 00000000000..2a2aa72fe8b
--- /dev/null
+++ b/backend/src/Designer/Controllers/Preview/V3/OldDataController.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using Altinn.Platform.Storage.Interface.Models;
+using Altinn.Studio.Designer.Filters;
+using Altinn.Studio.Designer.Models.Preview;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Routing;
+
+namespace Altinn.Studio.Designer.Controllers.Preview.V3
+{
+ [Authorize]
+ [AutoValidateAntiforgeryToken]
+ [Route("{org:regex(^(?!designer))}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/v3/instances/{partyId}/{instanceGuid}/data")]
+ public class OldDataController(
+ ) : Controller
+ {
+
+ [HttpGet("{dataGuid}")]
+ [UseSystemTextJson]
+ public ActionResult Get(
+ [FromRoute] string partyId,
+ [FromRoute] string instanceGuid
+ )
+ {
+ return Ok(partyId + "/" + instanceGuid);
+ }
+
+ [HttpPost]
+ [UseSystemTextJson]
+ public ActionResult Post(
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ [FromQuery] string dataType
+ )
+ {
+ return Created("link-to-app-placeholder", "{}");
+ }
+
+ [HttpDelete("{dataGuid}")]
+ public ActionResult Delete(
+ [FromRoute] Guid instanceGuid,
+ [FromRoute] Guid dataGuid
+ )
+ {
+ return Ok();
+ }
+
+ [HttpGet("{dataGuid}/validate")]
+ public ActionResult ValidateInstanceForData(
+ [FromRoute] Guid dataGuid
+ )
+ {
+ return Ok(new List());
+ }
+
+ [HttpPost("{dataGuid}/tags")]
+ public ActionResult UpdateTagsForAttachment(
+ [FromBody] string tag
+ )
+ {
+ return Created("link-to-app-placeholder", tag);
+ }
+ }
+}
diff --git a/backend/src/Designer/Controllers/Preview/V3/OldInstancesController.cs b/backend/src/Designer/Controllers/Preview/V3/OldInstancesController.cs
new file mode 100644
index 00000000000..b7240b9ec0d
--- /dev/null
+++ b/backend/src/Designer/Controllers/Preview/V3/OldInstancesController.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Web;
+using Altinn.App.Core.Internal.Process.Elements;
+using Altinn.Platform.Storage.Interface.Models;
+using Altinn.Studio.Designer.Filters;
+using Altinn.Studio.Designer.Helpers;
+using Altinn.Studio.Designer.Infrastructure.GitRepository;
+using Altinn.Studio.Designer.Services.Interfaces;
+using LibGit2Sharp;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Altinn.Studio.Designer.Controllers.Preview.V3;
+
+///
+/// Controller for preview support of older versions of Studio
+///
+[Authorize]
+[AutoValidateAntiforgeryToken]
+[Route("{org:regex(^(?!designer))}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/v3/instances")]
+public class OldInstancesController(IHttpContextAccessor httpContextAccessor,
+ IPreviewService previewService,
+ IAltinnGitRepositoryFactory altinnGitRepositoryFactory
+) : Controller
+{
+ ///
+ /// Get instance data
+ ///
+ [HttpGet("{partyId}/{instanceGuid}")]
+ [UseSystemTextJson]
+ public async Task> GetInstanceAsync(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken)
+ {
+ string refererHeader = Request.Headers["Referer"];
+ Uri refererUri = new(refererHeader);
+ string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ layoutSetName = string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ Instance instance = await previewService.GetMockInstance(org, app, AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext), partyId, layoutSetName, CancellationToken.None);
+ return Ok(instance);
+ }
+
+ ///
+ /// Create a new instance
+ ///
+ [HttpPost]
+ public async Task> Post(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromQuery] int instanceOwnerPartyId,
+ [FromQuery] string taskId,
+ [FromQuery] string language = null
+ )
+ {
+ string refererHeader = Request.Headers["Referer"];
+ Uri refererUri = new(refererHeader);
+ string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ layoutSetName = string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ Instance instance = await previewService.GetMockInstance(org, app, AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext), instanceOwnerPartyId, layoutSetName, CancellationToken.None);
+ return Ok(instance);
+ }
+
+ ///
+ /// Endpoint to get active instances for apps with state/layout sets/multiple processes
+ ///
+ /// A list of a single mocked instance
+ [HttpGet("{partyId}/active")]
+ public ActionResult> ActiveInstances(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId
+ )
+ {
+ // Simulate never having any active instances
+ List activeInstances = new();
+ return Ok(activeInstances);
+ }
+
+ ///
+ /// Endpoint to validate an instance
+ ///
+ /// Ok
+ [HttpGet("{partyId}/{instanceGuId}/validate")]
+ public ActionResult ValidateInstance()
+ {
+ return Ok();
+ }
+
+ ///
+ /// Action for getting a mocked response for the current task connected to the instance
+ ///
+ /// The processState
+ [HttpGet("{partyId}/{instanceGuid}/process")]
+ public async Task> Process(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken)
+ {
+ string developer = AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext);
+ string refererHeader = Request.Headers["Referer"];
+ Uri refererUri = new(refererHeader);
+ string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ layoutSetName = string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ Instance instance = await previewService.GetMockInstance(org, app, AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext), partyId, layoutSetName, CancellationToken.None);
+ List tasks = await previewService.GetTasksForAllLayoutSets(org, app, developer, cancellationToken);
+ AppProcessState processState = new(instance.Process)
+ {
+ ProcessTasks = tasks != null
+ ? new List(tasks?.ConvertAll(task => new AppProcessTaskTypeInfo { ElementId = task, AltinnTaskType = "data" }))
+ : null
+ };
+
+ return Ok(processState);
+ }
+
+ ///
+ /// Action for getting a mocked response for the next task connected to the instance
+ ///
+ /// The processState object on the global mockInstance object
+ [HttpGet("{partyId}/{instanceGuid}/process/next")]
+ public async Task ProcessNextAsync(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ CancellationToken cancellationToken
+ )
+ {
+ string refererHeader = Request.Headers["Referer"];
+ Uri refererUri = new(refererHeader);
+ string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ layoutSetName = string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ Instance instance = await previewService.GetMockInstance(org, app, AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext), partyId, layoutSetName, CancellationToken.None);
+ return Ok(instance.Process);
+ }
+
+ ///
+ /// Action for mocking an end to the process in order to get receipt after "send inn" is pressed
+ ///
+ /// Process object where ended is set
+ [HttpPut("{partyId}/{instanceGuid}/process/next")]
+ public async Task UpdateProcessNext(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] int partyId,
+ [FromRoute] Guid instanceGuid,
+ [FromQuery] string lang,
+ CancellationToken cancellationToken
+ )
+ {
+ string refererHeader = Request.Headers.Referer;
+ Uri refererUri = new(refererHeader);
+ string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];
+ layoutSetName = string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
+ Instance instance = await previewService.GetMockInstance(org, app, AuthenticationHelper.GetDeveloperUserName(httpContextAccessor.HttpContext), partyId, layoutSetName, CancellationToken.None);
+ return Ok(instance.Process);
+ }
+
+ ///
+ /// Action for getting options list for a given options list id for a given instance
+ ///
+ [HttpGet("{partyId}/{instanceGuid}/options/{optionListId}")]
+ public async Task> GetOptionsForInstance(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] string optionListId,
+ [FromQuery] string language,
+ [FromQuery] string source,
+ CancellationToken cancellationToken
+ )
+ {
+ try
+ {
+ // TODO: Need code to get dynamic options list based on language and source?
+ string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
+ AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
+ string options = await altinnAppGitRepository.GetOptionsList(optionListId, cancellationToken);
+ return Ok(options);
+ }
+ catch (NotFoundException)
+ {
+ // Return empty list since app-frontend don't handle a null result
+ return Ok(new List());
+ }
+ }
+
+ ///
+ /// Action for getting data list for a given data list id for a given instance
+ ///
+ [HttpGet("{partyId}/{instanceGuid}/datalists/{dataListId}")]
+ public ActionResult> GetDataListsForInstance(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromRoute] string dataListId,
+ [FromQuery] string language,
+ [FromQuery] string size,
+ CancellationToken cancellationToken
+ )
+ {
+ // TODO: Should look into whether we can get some actual data here, or if we can make an "informed" mock based on the setup.
+ // For now, we just return an empty list.
+ return Ok(new List());
+ }
+
+ ///
+ /// Action for updating data model with tag for attachment component // TODO: Figure out what actually happens here
+ ///
+ [HttpPost("{partyId}/{instanceGuid}/pages/order")]
+ public IActionResult UpdateAttachmentWithTag(
+ [FromRoute] string org,
+ [FromRoute] string app,
+ [FromQuery] string currentPage,
+ [FromQuery] string layoutSetId,
+ [FromQuery] string dataTypeId
+ )
+ {
+ return Ok();
+ }
+}
diff --git a/backend/src/Designer/Controllers/PreviewController.cs b/backend/src/Designer/Controllers/PreviewController.cs
index 5a3c74245d3..8baf107aae1 100644
--- a/backend/src/Designer/Controllers/PreviewController.cs
+++ b/backend/src/Designer/Controllers/PreviewController.cs
@@ -142,12 +142,6 @@ public async Task> ApplicationMetadata(string
string appNugetVersionString = _appDevelopmentService.GetAppLibVersion(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer)).ToString();
// This property is populated at runtime by the apps, so we need to mock it here
applicationMetadata.AltinnNugetVersion = GetMockedAltinnNugetBuildFromVersion(appNugetVersionString);
- if (altinnAppGitRepository.AppUsesLayoutSets())
- {
- LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken);
- applicationMetadata = SetMockDataTypeIfMissing(applicationMetadata, layoutSets);
- }
-
applicationMetadata = SetMockedPartyTypesAllowedAsAllFalse(applicationMetadata);
return Ok(applicationMetadata);
}
@@ -192,8 +186,7 @@ public async Task> LayoutSets(string org, string app, C
string developer = AuthenticationHelper.GetDeveloperUserName(_httpContextAccessor.HttpContext);
AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken);
- LayoutSets layoutSetsWithMockedDataTypes = AddDataTypesToReturnedLayoutSetsIfMissing(layoutSets);
- return Ok(layoutSetsWithMockedDataTypes);
+ return Ok(layoutSets);
}
catch (NotFoundException)
{
@@ -739,33 +732,6 @@ private static ApplicationMetadata SetMockedPartyTypesAllowedAsAllFalse(Applicat
return applicationMetadata;
}
- private static ApplicationMetadata SetMockDataTypeIfMissing(ApplicationMetadata applicationMetadata, LayoutSets layoutSets)
- {
- LayoutSets layoutSetsWithMockedDataTypesIfMissing = AddDataTypesToReturnedLayoutSetsIfMissing(layoutSets);
- layoutSetsWithMockedDataTypesIfMissing.Sets.ForEach(set =>
- {
- if (set.Tasks?[0] == Constants.General.CustomReceiptId)
- {
- return;
- }
-
- if (!applicationMetadata.DataTypes.Any(dataType => dataType.Id == set.DataType))
- {
- applicationMetadata.DataTypes.Add(new DataType()
- {
- Id = set.DataType,
- AppLogic = new ApplicationLogic()
- {
- ClassRef = $"Altinn.App.Models.model.{set.DataType}"
- },
- TaskId = set.Tasks?[0]
- });
- }
- });
-
- return applicationMetadata;
- }
-
private bool IsValidSemVerVersion(string[] versionParts)
{
return versionParts.Length >= 3 && Convert.ToInt32(versionParts[0]) >= 8;
@@ -780,17 +746,5 @@ private int GetPreviewVersion(string[] versionParts)
{
return Convert.ToInt32(versionParts[3]);
}
-
- private static LayoutSets AddDataTypesToReturnedLayoutSetsIfMissing(LayoutSets layoutSets)
- {
- int counter = 0;
- foreach (var set in layoutSets.Sets.Where(set => string.IsNullOrEmpty(set.DataType)))
- {
- string mockDataTypeId = $"{PreviewService.MockDataModelIdPrefix}-{counter++}";
- set.DataType = mockDataTypeId;
- }
-
- return layoutSets;
- }
}
}
diff --git a/backend/src/Designer/Controllers/ResourceAdminController.cs b/backend/src/Designer/Controllers/ResourceAdminController.cs
index a6ac0fc4c38..ad3f565ba20 100644
--- a/backend/src/Designer/Controllers/ResourceAdminController.cs
+++ b/backend/src/Designer/Controllers/ResourceAdminController.cs
@@ -610,7 +610,7 @@ private async Task GetOrgList()
return orgList;
}
- private static bool IsServiceOwner(ServiceResource? resource, string loggedInOrg)
+ private static bool IsServiceOwner(ServiceResource resource, string loggedInOrg)
{
if (resource?.HasCompetentAuthority == null)
{
diff --git a/backend/src/Designer/Helpers/AppFrontendVersionHelper.cs b/backend/src/Designer/Helpers/AppFrontendVersionHelper.cs
index 5e4efba4cfd..71b681054d0 100644
--- a/backend/src/Designer/Helpers/AppFrontendVersionHelper.cs
+++ b/backend/src/Designer/Helpers/AppFrontendVersionHelper.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
+using HtmlAgilityPack;
namespace Altinn.Studio.Designer.Helpers;
@@ -9,13 +10,29 @@ public static class AppFrontendVersionHelper
private const string SemanticVersionRegex = @"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$";
private const string ExtendedVersion = @"^(\d+)(\.\d+)?$";
+ // allow overwriting altinn-app-frontend version with a meta tag
+ // i.e.
+ private static string getMetaTagVersion(HtmlDocument htmlDoc)
+ {
+ HtmlNode metaTag = htmlDoc.DocumentNode.SelectSingleNode("//meta[@data-altinn-app-frontend-version]");
+ return metaTag?.GetAttributeValue("data-altinn-app-frontend-version", null);
+ }
+
public static bool TryGetFrontendVersionFromIndexFile(string filePath, out string version)
{
version = null;
string fileContent = File.ReadAllText(filePath);
- var htmlDoc = new HtmlAgilityPack.HtmlDocument();
+ var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(fileContent);
+
+ string metaTagVersion = getMetaTagVersion(htmlDoc);
+ if (metaTagVersion != null)
+ {
+ version = metaTagVersion;
+ return true;
+ }
+
var scriptTag = htmlDoc.DocumentNode.SelectSingleNode(
"//script[contains(@src, 'https://altinncdn.no/toolkits/altinn-app-frontend') and contains(@src, 'altinn-app-frontend.js')]");
diff --git a/backend/src/Designer/Infrastructure/GitRepository/AltinnAppGitRepository.cs b/backend/src/Designer/Infrastructure/GitRepository/AltinnAppGitRepository.cs
index b0c3c5ed527..db8ba9527dd 100644
--- a/backend/src/Designer/Infrastructure/GitRepository/AltinnAppGitRepository.cs
+++ b/backend/src/Designer/Infrastructure/GitRepository/AltinnAppGitRepository.cs
@@ -15,6 +15,7 @@
using Altinn.Studio.Designer.Helpers;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Models.App;
+using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.TypedHttpClients.Exceptions;
using LibGit2Sharp;
using JsonSerializer = System.Text.Json.JsonSerializer;
@@ -504,6 +505,94 @@ public async Task GetLayoutSettingsAndCreateNewIfNotFound(string layou
return layoutSettings;
}
+ ///
+ /// Finds all in a given layout.
+ ///
+ /// The layout.
+ /// A list of occurrences to append any optionListIdRefs in the layout to.
+ /// The layoutSetName the layout belongs to.
+ /// The name of the given layout.
+ /// A list of .
+ public List FindOptionListReferencesInLayout(JsonNode layout, List refToOptionListSpecifiers, string layoutSetName, string layoutName)
+ {
+ var optionListIds = GetOptionsListIds();
+ var layoutArray = layout["data"]?["layout"] as JsonArray;
+ if (layoutArray == null)
+ {
+ return refToOptionListSpecifiers;
+ }
+
+ foreach (var item in layoutArray)
+ {
+ string optionListId = item["optionsId"]?.ToString();
+
+ if (!optionListIds.Contains(optionListId))
+ {
+ continue;
+ }
+
+ if (!String.IsNullOrEmpty(optionListId))
+ {
+ if (OptionListIdAlreadyOccurred(refToOptionListSpecifiers, optionListId, out var existingRef))
+ {
+ if (OptionListIdAlreadyOccurredInLayout(existingRef, layoutSetName, layoutName, out var existingSource))
+ {
+ existingSource.ComponentIds.Add(item["id"]?.ToString());
+ }
+ else
+ {
+ AddNewOptionListIdSource(existingRef, layoutSetName, layoutName, item["id"]?.ToString());
+ }
+ }
+ else
+ {
+ AddNewRefToOptionListSpecifier(refToOptionListSpecifiers, optionListId, layoutSetName, layoutName, item["id"]?.ToString());
+ }
+ }
+ }
+ return refToOptionListSpecifiers;
+ }
+
+ private bool OptionListIdAlreadyOccurred(List refToOptionListSpecifiers, string optionListId, out RefToOptionListSpecifier existingRef)
+ {
+ existingRef = refToOptionListSpecifiers.FirstOrDefault(refToOptionList => refToOptionList.OptionListId == optionListId);
+ return existingRef != null;
+ }
+
+ private bool OptionListIdAlreadyOccurredInLayout(RefToOptionListSpecifier refToOptionListSpecifier, string layoutSetName, string layoutName, out OptionListIdSource existingSource)
+ {
+ existingSource = refToOptionListSpecifier.OptionListIdSources
+ .FirstOrDefault(optionListIdSource => optionListIdSource.LayoutSetId == layoutSetName && optionListIdSource.LayoutName == layoutName);
+ return existingSource != null;
+ }
+
+ private void AddNewRefToOptionListSpecifier(List refToOptionListSpecifiers, string optionListId, string layoutSetName, string layoutName, string componentId)
+ {
+ refToOptionListSpecifiers.Add(new()
+ {
+ OptionListId = optionListId,
+ OptionListIdSources =
+ [
+ new OptionListIdSource
+ {
+ LayoutSetId = layoutSetName,
+ LayoutName = layoutName,
+ ComponentIds = [componentId]
+ }
+ ]
+ });
+ }
+
+ private void AddNewOptionListIdSource(RefToOptionListSpecifier refToOptionListSpecifier, string layoutSetName, string layoutName, string componentId)
+ {
+ refToOptionListSpecifier.OptionListIdSources.Add(new OptionListIdSource
+ {
+ LayoutSetId = layoutSetName,
+ LayoutName = layoutName,
+ ComponentIds = [componentId]
+ });
+ }
+
private async Task CreateLayoutSettings(string layoutSetName)
{
string layoutSetPath = GetPathToLayoutSet(layoutSetName);
diff --git a/backend/src/Designer/Infrastructure/GitRepository/LocalGitCloneIoException.cs b/backend/src/Designer/Infrastructure/GitRepository/LocalGitCloneIoException.cs
index 4018eb27933..485fff54d02 100644
--- a/backend/src/Designer/Infrastructure/GitRepository/LocalGitCloneIoException.cs
+++ b/backend/src/Designer/Infrastructure/GitRepository/LocalGitCloneIoException.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.Serialization;
namespace Altinn.Studio.Designer.Infrastructure.GitRepository;
@@ -23,10 +22,5 @@ public LocalGitCloneIoException(string message) : base(message)
public LocalGitCloneIoException(string message, Exception innerException) : base(message, innerException)
{
}
-
- ///
- protected LocalGitCloneIoException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
}
diff --git a/backend/src/Designer/Infrastructure/ServiceRegistration.cs b/backend/src/Designer/Infrastructure/ServiceRegistration.cs
index 8aba45e2e11..5d3b0607d8b 100644
--- a/backend/src/Designer/Infrastructure/ServiceRegistration.cs
+++ b/backend/src/Designer/Infrastructure/ServiceRegistration.cs
@@ -73,6 +73,7 @@ public static IServiceCollection RegisterServiceImplementations(this IServiceCol
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.RegisterDatamodeling(configuration);
diff --git a/backend/src/Designer/Models/AccessList.cs b/backend/src/Designer/Models/AccessList.cs
index 0718d478824..6169364507d 100644
--- a/backend/src/Designer/Models/AccessList.cs
+++ b/backend/src/Designer/Models/AccessList.cs
@@ -8,8 +8,8 @@ namespace Altinn.Studio.Designer.Models
public class AccessList : HeaderEtag
{
- public string Identifier { get; set; }
- public string Name { get; set; }
+ public required string Identifier { get; set; }
+ public required string Name { get; set; }
public string? Description { get; set; }
public IEnumerable? ResourceConnections { get; set; }
}
diff --git a/backend/src/Designer/Models/AccessListMember.cs b/backend/src/Designer/Models/AccessListMember.cs
index 0898f1fcb8c..99169b1d372 100644
--- a/backend/src/Designer/Models/AccessListMember.cs
+++ b/backend/src/Designer/Models/AccessListMember.cs
@@ -1,9 +1,10 @@
-namespace Altinn.Studio.Designer.Models
+#nullable enable
+namespace Altinn.Studio.Designer.Models
{
public class AccessListMember
{
- public string OrgNr { get; set; }
- public string OrgName { get; set; }
- public bool IsSubParty { get; set; }
+ public required string OrgNr { get; set; }
+ public required string OrgName { get; set; }
+ public bool? IsSubParty { get; set; }
}
}
diff --git a/backend/src/Designer/Models/BrregPartyResultSet.cs b/backend/src/Designer/Models/BrregPartyResultSet.cs
index 462dff0f20d..38fcd6eae33 100644
--- a/backend/src/Designer/Models/BrregPartyResultSet.cs
+++ b/backend/src/Designer/Models/BrregPartyResultSet.cs
@@ -7,7 +7,7 @@ namespace Altinn.Studio.Designer.Models
public class BrregParty
{
[JsonPropertyName("organisasjonsnummer")]
- public string Organisasjonsnummer { get; set; }
+ public required string Organisasjonsnummer { get; set; }
[JsonPropertyName("navn")]
public string? Navn { get; set; }
}
diff --git a/backend/src/Designer/Models/CreateAccessListModel.cs b/backend/src/Designer/Models/CreateAccessListModel.cs
index 23629565f21..9e16d9ec020 100644
--- a/backend/src/Designer/Models/CreateAccessListModel.cs
+++ b/backend/src/Designer/Models/CreateAccessListModel.cs
@@ -3,7 +3,7 @@ namespace Altinn.Studio.Designer.Models
{
public class CreateAccessListModel
{
- public string Name { get; set; }
+ public required string Name { get; set; }
public string? Description { get; set; }
}
}
diff --git a/backend/src/Designer/Models/Dto/AccessListInfoDtoPaginated.cs b/backend/src/Designer/Models/Dto/AccessListInfoDtoPaginated.cs
index ae755d69509..574102977eb 100644
--- a/backend/src/Designer/Models/Dto/AccessListInfoDtoPaginated.cs
+++ b/backend/src/Designer/Models/Dto/AccessListInfoDtoPaginated.cs
@@ -5,7 +5,7 @@ namespace Altinn.Studio.Designer.Models.Dto
{
public class AccessListInfoDtoPaginated
{
- public IEnumerable Data { get; set; }
+ public required IEnumerable Data { get; set; }
public AccessListPaging? Links { get; set; }
}
}
diff --git a/backend/src/Designer/Models/Dto/AccessListMember.cs b/backend/src/Designer/Models/Dto/AccessListMember.cs
index 3ab21eb4a52..752a4d485eb 100644
--- a/backend/src/Designer/Models/Dto/AccessListMember.cs
+++ b/backend/src/Designer/Models/Dto/AccessListMember.cs
@@ -1,34 +1,35 @@
-using System.Collections.Generic;
+#nullable enable
+using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Altinn.Studio.Designer.Models.Dto
{
public class AccessListMembersDto
{
- public IList Data { get; set; }
+ public required IList Data { get; set; }
public AccessListPaging? Links { get; set; }
}
public class AccessListMemberDataDto
{
- public string Id { get; set; }
- public string Since { get; set; }
- public AccessListMemberDtoIdentifier Identifiers { get; set; }
+ public required string Id { get; set; }
+ public required string Since { get; set; }
+ public required AccessListMemberDtoIdentifier Identifiers { get; set; }
}
public class AccessListMemberDtoIdentifier
{
[JsonPropertyName("urn:altinn:party:uuid")]
- public string PartyUuid { get; set; }
+ public required string PartyUuid { get; set; }
[JsonPropertyName("urn:altinn:party:id")]
- public int PartyId { get; set; }
+ public required int PartyId { get; set; }
[JsonPropertyName("urn:altinn:organization:identifier-no")]
- public string OrganizationNumber { get; set; }
+ public required string OrganizationNumber { get; set; }
}
public class UpdateAccessListMemberDto
{
- public IList Data { get; set; }
+ public required IList Data { get; set; }
}
diff --git a/backend/src/Designer/Models/Dto/OptionListReferences.cs b/backend/src/Designer/Models/Dto/OptionListReferences.cs
new file mode 100644
index 00000000000..b0224f0ded4
--- /dev/null
+++ b/backend/src/Designer/Models/Dto/OptionListReferences.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Altinn.Studio.Designer.Models.Dto;
+
+public class RefToOptionListSpecifier
+{
+ [JsonPropertyName("optionListId")]
+ public string OptionListId { get; set; }
+ [JsonPropertyName("optionListIdSources")]
+ public List OptionListIdSources { get; set; }
+}
+
+public class OptionListIdSource
+{
+ [JsonPropertyName("layoutSetId")]
+ public string LayoutSetId { get; set; }
+ [JsonPropertyName("layoutName")]
+ public string LayoutName { get; set; }
+ [JsonPropertyName("componentIds")]
+ public List ComponentIds { get; set; }
+}
diff --git a/backend/src/Designer/Models/LayoutSets.cs b/backend/src/Designer/Models/LayoutSets.cs
index 9efb83fba5a..0eb4e18019b 100644
--- a/backend/src/Designer/Models/LayoutSets.cs
+++ b/backend/src/Designer/Models/LayoutSets.cs
@@ -1,40 +1,36 @@
#nullable enable
using System.Collections.Generic;
using System.Text.Json.Serialization;
-using JetBrains.Annotations;
namespace Altinn.Studio.Designer.Models;
public class LayoutSets : Altinn.App.Core.Models.LayoutSets
{
[JsonPropertyName("$schema")]
- public string Schema { get; set; }
+ public required string Schema { get; set; }
[JsonPropertyName("sets")]
- public new List Sets { get; set; }
+ public new required List Sets { get; set; }
[JsonExtensionData]
- public IDictionary UnknownProperties { get; set; }
+ public IDictionary? UnknownProperties { get; set; }
}
public class LayoutSetConfig
{
[JsonPropertyName("id")]
- public string Id { get; set; }
+ public required string Id { get; set; }
- [JsonPropertyName("dataType")]
- [CanBeNull]
- public string DataType { get; set; }
+ [JsonPropertyName("dataType")] public string? DataType { get; set; }
[JsonPropertyName("tasks")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [CanBeNull]
- public List Tasks { get; set; }
+ public List? Tasks { get; set; }
[JsonPropertyName("type")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string Type { get; set; }
+ public string? Type { get; set; }
[JsonExtensionData]
- public IDictionary UnknownProperties { get; set; }
+ public IDictionary? UnknownProperties { get; set; }
}
diff --git a/backend/src/Designer/Models/ListviewServiceResource.cs b/backend/src/Designer/Models/ListviewServiceResource.cs
index 944cbde913c..5a69223f079 100644
--- a/backend/src/Designer/Models/ListviewServiceResource.cs
+++ b/backend/src/Designer/Models/ListviewServiceResource.cs
@@ -22,7 +22,7 @@ public class ListviewServiceResource
public string? CreatedBy { get; set; }
///
- /// Timestamp for when the resourcefile was last changed
+ /// Timestamp for when the resource file was last changed
///
public DateTime? LastChanged { get; set; }
@@ -34,6 +34,6 @@ public class ListviewServiceResource
///
/// A list of environments the resource is deployed in
///
- public IList Environments { get; set; }
+ public IList? Environments { get; set; }
}
}
diff --git a/backend/src/Designer/Models/PagedAccessListResponse.cs b/backend/src/Designer/Models/PagedAccessListResponse.cs
index b1fdfd708af..39b20befd77 100644
--- a/backend/src/Designer/Models/PagedAccessListResponse.cs
+++ b/backend/src/Designer/Models/PagedAccessListResponse.cs
@@ -5,7 +5,7 @@ namespace Altinn.Studio.Designer.Models
{
public class PagedAccessListResponse
{
- public IEnumerable Data { get; set; }
+ public IEnumerable? Data { get; set; }
public string? NextPage { get; set; }
}
}
diff --git a/backend/src/Designer/Models/Preview/DataPatchRequest.cs b/backend/src/Designer/Models/Preview/DataPatchRequest.cs
index 033279247b1..d2472d6c277 100644
--- a/backend/src/Designer/Models/Preview/DataPatchRequest.cs
+++ b/backend/src/Designer/Models/Preview/DataPatchRequest.cs
@@ -1,3 +1,4 @@
+#nullable enable
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Json.Patch;
diff --git a/backend/src/Designer/Models/Preview/DataPatchRequestMultiple.cs b/backend/src/Designer/Models/Preview/DataPatchRequestMultiple.cs
new file mode 100644
index 00000000000..bdc0da5eb08
--- /dev/null
+++ b/backend/src/Designer/Models/Preview/DataPatchRequestMultiple.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+using Json.Patch;
+
+namespace Altinn.Studio.Designer.Models.Preview;
+
+///
+/// Represents the request to patch data on the .
+/// This version allows multiple patches to be applied by the same request.
+///
+public class DataPatchRequestMultiple
+{
+ ///
+ /// List of patches to apply.
+ ///
+ [JsonPropertyName("patches")]
+ public required List Patches { get; init; }
+
+ ///
+ /// Item class for the list of Patches
+ ///
+ /// The guid of the data element to patch
+ /// The patch to apply
+ public record PatchListItem
+ (
+ [property: JsonPropertyName("dataElementId")] Guid DataElementId,
+ [property: JsonPropertyName("patch")] JsonPatch Patch
+ );
+
+ public required List? IgnoredValidators { get; init; }
+}
diff --git a/backend/src/Designer/Models/Preview/DataPatchResponseMultiple.cs b/backend/src/Designer/Models/Preview/DataPatchResponseMultiple.cs
new file mode 100644
index 00000000000..b793b2589d8
--- /dev/null
+++ b/backend/src/Designer/Models/Preview/DataPatchResponseMultiple.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+using Altinn.Platform.Storage.Interface.Models;
+
+namespace Altinn.Studio.Designer.Models.Preview;
+
+///
+/// Represents the response from a data patch operation on the .
+///
+public class DataPatchResponseMultiple
+{
+ ///
+ /// The validation issues that were found during the patch operation.
+ ///
+ [JsonPropertyName("validationIssues")]
+ public required List ValidationIssues { get; init; }
+
+ ///
+ /// The current data in all data models updated by the patch operation.
+ ///
+ [JsonPropertyName("newDataModels")]
+ public required List NewDataModels { get; init; }
+
+ ///
+ /// The instance with updated dataElement list.
+ ///
+ [JsonPropertyName("instance")]
+ public required Instance Instance { get; init; }
+}
+
+///
+/// Pair of Guid and data object.
+///
+/// The guid of the DataElement
+/// The form data of the data element
+public record DataModelPairResponse(
+ [property: JsonPropertyName("dataElementId")] Guid DataElementId,
+ [property: JsonPropertyName("data")] object Data
+);
diff --git a/backend/src/Designer/Models/Preview/DataPostResponse.cs b/backend/src/Designer/Models/Preview/DataPostResponse.cs
new file mode 100644
index 00000000000..d4886d7212b
--- /dev/null
+++ b/backend/src/Designer/Models/Preview/DataPostResponse.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text.Json.Serialization;
+using Altinn.Platform.Storage.Interface.Models;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Altinn.Studio.Designer.Models.Preview;
+
+///
+/// Response object for POST and DELETE to /org/app/instances/{instanceOwnerPartyId:int}/{instanceGuid:guid}/data/{dataType}
+///
+public class DataPostResponse
+{
+ ///
+ /// The Id of the created data element
+ ///
+ [JsonPropertyName("newDataElementId")]
+ public required Guid NewDataElementId { get; init; }
+
+ ///
+ /// The instance with updated data
+ ///
+ [JsonPropertyName("instance")]
+ public required Instance Instance { get; init; }
+
+ ///
+ /// List of validation issues that reported to have relevant changes after a new data element was added
+ ///
+ [JsonPropertyName("validationIssues")]
+ public required List ValidationIssues { get; init; }
+
+ ///
+ /// List of updated DataModels caused by dataProcessing
+ ///
+ [JsonPropertyName("newDataModels")]
+ public required List NewDataModels { get; init; }
+}
+
+///
+/// Extension of ProblemDetails to include Validation issues from the file upload.
+///
+public class DataPostErrorResponse : ProblemDetails
+{
+ ///
+ /// Constructor for simple initialization from upload validation issues.
+ ///
+ public DataPostErrorResponse(string detail, List validationIssues)
+ {
+ Title = "File validation failed";
+ Detail = detail;
+ Status = (int)HttpStatusCode.BadRequest;
+ UploadValidationIssues = validationIssues;
+ }
+
+ ///
+ /// List of the validators that reported to have relevant changes after a new data element was added
+ ///
+ [JsonPropertyName("uploadValidationIssues")]
+ public List UploadValidationIssues { get; }
+}
diff --git a/backend/src/Designer/Models/Preview/ValidationIssueWithSource.cs b/backend/src/Designer/Models/Preview/ValidationIssueWithSource.cs
new file mode 100644
index 00000000000..f8996115d7b
--- /dev/null
+++ b/backend/src/Designer/Models/Preview/ValidationIssueWithSource.cs
@@ -0,0 +1,112 @@
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+using Altinn.App.Core.Models.Validation;
+
+namespace Altinn.Studio.Designer.Models.Preview;
+
+///
+/// Represents a detailed message from validation.
+///
+public class ValidationIssueWithSource
+{
+ ///
+ /// Converter function to create a from a and adding a source.
+ ///
+ public static ValidationIssueWithSource FromIssue(ValidationIssue issue, string source, bool noIncrementalUpdates)
+ {
+ return new ValidationIssueWithSource
+ {
+ Severity = issue.Severity,
+ DataElementId = issue.DataElementId,
+ Field = issue.Field,
+ Code = issue.Code,
+ Description = issue.Description,
+ Source = source,
+ NoIncrementalUpdates = noIncrementalUpdates,
+ CustomTextKey = issue.CustomTextKey,
+ CustomTextParams = issue.CustomTextParams,
+ };
+ }
+
+ ///
+ /// The seriousness of the identified issue.
+ ///
+ ///
+ /// This property is serialized in json as a number
+ /// 1: Error (something needs to be fixed)
+ /// 2: Warning (does not prevent submission)
+ /// 3: Information (hint shown to the user)
+ /// 4: Fixed (obsolete, only used for v3 of frontend)
+ /// 5: Success (Inform the user that something was completed with success)
+ ///
+ [JsonPropertyName("severity")]
+ [JsonConverter(typeof(JsonNumberEnumConverter))]
+ public required ValidationIssueSeverity Severity { get; set; }
+
+ ///
+ /// The unique id of the data element of a given instance with the identified issue.
+ ///
+ [JsonPropertyName("dataElementId")]
+ public string? DataElementId { get; set; }
+
+ ///
+ /// A reference to a property the issue is about.
+ ///
+ [JsonPropertyName("field")]
+ public string? Field { get; set; }
+
+ ///
+ /// A system readable identification of the type of issue.
+ /// Eg:
+ ///
+ [JsonPropertyName("code")]
+ public required string? Code { get; set; }
+
+ ///
+ /// A human readable description of the issue.
+ ///
+ [JsonPropertyName("description")]
+ public required string? Description { get; set; }
+
+ ///
+ /// The short name of the class that crated the message (set automatically after return of list)
+ ///
+ [JsonPropertyName("source")]
+ public required string Source { get; set; }
+
+ ///
+ /// Weather the issue is from a validator that correctly implements .
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
+ [JsonPropertyName("noIncrementalUpdates")]
+ public bool NoIncrementalUpdates { get; set; }
+
+ ///
+ /// The custom text key to use for the localized text in the frontend.
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("customTextKey")]
+ public string? CustomTextKey { get; set; }
+
+ ///
+ /// might include some parameters (typically the field value, or some derived value)
+ /// that should be included in error message.
+ ///
+ ///
+ /// The localized text for the key might be "Date must be between {0} and {1}"
+ /// and the param will provide the dynamical range of allowable dates (eg teh reporting period)
+ ///
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("customTextParams")]
+ public List? CustomTextParams { get; set; }
+}
+
+///
+/// API responses that returns validation issues grouped by source, typically return a list of these.
+///
+/// The for the Validator that created theese issues
+/// List of issues
+public record ValidationSourcePair(
+ [property: JsonPropertyName("source")] string Source,
+ [property: JsonPropertyName("issues")] List Issues
+);
diff --git a/backend/src/Designer/Models/ServiceResource.cs b/backend/src/Designer/Models/ServiceResource.cs
index 3f76576f410..407eeee1fc6 100644
--- a/backend/src/Designer/Models/ServiceResource.cs
+++ b/backend/src/Designer/Models/ServiceResource.cs
@@ -6,7 +6,7 @@
namespace Altinn.Studio.Designer.Models
{
///
- /// Model describing a complete resource from the resrouce registry
+ /// Model describing a complete resource from the resource registry
///
public class ServiceResource
{
@@ -54,7 +54,7 @@ public class ServiceResource
///
/// List of possible contact points
///
- public List ContactPoints { get; set; }
+ public List? ContactPoints { get; set; }
///
/// Linkes to the outcome of a public service
diff --git a/backend/src/Designer/Program.cs b/backend/src/Designer/Program.cs
index bae7c0a7425..cd668a551f4 100644
--- a/backend/src/Designer/Program.cs
+++ b/backend/src/Designer/Program.cs
@@ -351,13 +351,4 @@ void CreateDirectory(IConfiguration configuration)
}
}
-static string GetXmlCommentsPathForControllers()
-{
- // locate the xml file being generated by .NET
- string xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.XML";
- string xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
-
- return xmlPath;
-}
-
public partial class Program { }
diff --git a/backend/src/Designer/RepositoryClient/Model/ContentsResponse.cs b/backend/src/Designer/RepositoryClient/Model/ContentsResponse.cs
index 7117cf335d0..c696f26bf97 100644
--- a/backend/src/Designer/RepositoryClient/Model/ContentsResponse.cs
+++ b/backend/src/Designer/RepositoryClient/Model/ContentsResponse.cs
@@ -8,48 +8,48 @@ namespace Altinn.Studio.Designer.RepositoryClient.Model
public class ContentsResponse
{
[JsonProperty("_links")]
- public FileLinksResponse Links { get; set; }
+ public required FileLinksResponse Links { get; set; }
[JsonProperty("content")]
- public string? Content { get; set; }
+ public required string? Content { get; set; }
[JsonProperty("download_url")]
- public string DownloadUrl { get; set; }
+ public required string DownloadUrl { get; set; }
[JsonProperty("encoding")]
- public string? Encoding { get; set; }
+ public required string? Encoding { get; set; }
[JsonProperty("git_url")]
- public string GitUrl { get; set; }
+ public required string GitUrl { get; set; }
[JsonProperty("html_url")]
- public string HtmlUrl { get; set; }
+ public required string HtmlUrl { get; set; }
[JsonProperty("last_commit_sha")]
- public string LastCommitSha { get; set; }
+ public required string LastCommitSha { get; set; }
[JsonProperty("name")]
- public string Name { get; set; }
+ public required string Name { get; set; }
[JsonProperty("path")]
- public string Path { get; set; }
+ public required string Path { get; set; }
[JsonProperty("sha")]
- public string Sha { get; set; }
+ public required string Sha { get; set; }
[JsonProperty("size")]
- public int Size { get; set; }
+ public required int Size { get; set; }
[JsonProperty("submodule_git_url")]
- public string SubmoduleGitUrl { get; set; }
+ public required string SubmoduleGitUrl { get; set; }
[JsonProperty("target")]
public string? Target { get; set; }
[JsonProperty("type")]
- public string Type { get; set; }
+ public required string Type { get; set; }
[JsonProperty("url")]
- public string Url { get; set; }
+ public required string Url { get; set; }
}
}
diff --git a/backend/src/Designer/Services/Implementation/MaskinPortenClientDefinition.cs b/backend/src/Designer/Services/Implementation/MaskinPortenClientDefinition.cs
index 6431d810b79..47523483422 100644
--- a/backend/src/Designer/Services/Implementation/MaskinPortenClientDefinition.cs
+++ b/backend/src/Designer/Services/Implementation/MaskinPortenClientDefinition.cs
@@ -19,14 +19,14 @@ public MaskinPortenClientDefinition(IOptions clientS
ClientSettings = clientSettings.Value;
}
- public async Task GetClientSecrets()
+ public Task GetClientSecrets()
{
ClientSecrets clientSecrets = new ClientSecrets();
byte[] base64EncodedBytes = Convert.FromBase64String(ClientSettings.EncodedJwk);
string jwkjson = Encoding.UTF8.GetString(base64EncodedBytes);
clientSecrets.ClientKey = new Microsoft.IdentityModel.Tokens.JsonWebKey(jwkjson);
- return clientSecrets;
+ return Task.FromResult(clientSecrets);
}
}
}
diff --git a/backend/src/Designer/Services/Implementation/OptionsService.cs b/backend/src/Designer/Services/Implementation/OptionsService.cs
index 5dc4e7a26a4..591daad2a30 100644
--- a/backend/src/Designer/Services/Implementation/OptionsService.cs
+++ b/backend/src/Designer/Services/Implementation/OptionsService.cs
@@ -6,6 +6,7 @@
using Altinn.Studio.Designer.Exceptions.Options;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
+using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.Services.Interfaces;
using LibGit2Sharp;
using Microsoft.AspNetCore.Http;
@@ -62,10 +63,33 @@ public async Task> GetOptionsList(string org, string repo, string d
throw new InvalidOptionsFormatException($"One or more of the options have an invalid format in option list: {optionsListId}.");
}
-
return optionsList;
}
+ ///
+ public async Task> GetAllOptionListReferences(AltinnRepoEditingContext altinnRepoEditingContext, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ AltinnAppGitRepository altinnAppGitRepository =
+ _altinnGitRepositoryFactory.GetAltinnAppGitRepository(altinnRepoEditingContext.Org,
+ altinnRepoEditingContext.Repo, altinnRepoEditingContext.Developer);
+
+ List optionsListReferences = new List();
+
+ string[] layoutSetNames = altinnAppGitRepository.GetLayoutSetNames();
+ foreach (string layoutSetName in layoutSetNames)
+ {
+ string[] layoutNames = altinnAppGitRepository.GetLayoutNames(layoutSetName);
+ foreach (var layoutName in layoutNames)
+ {
+ var layout = await altinnAppGitRepository.GetLayout(layoutSetName, layoutName, cancellationToken);
+ optionsListReferences = altinnAppGitRepository.FindOptionListReferencesInLayout(layout, optionsListReferences, layoutSetName, layoutName);
+ }
+ }
+
+ return optionsListReferences;
+ }
+
private void ValidateOption(Option option)
{
var validationContext = new ValidationContext(option);
diff --git a/backend/src/Designer/Services/Implementation/Preview/DataService.cs b/backend/src/Designer/Services/Implementation/Preview/DataService.cs
index 75a00b64155..5f6ebca7fcd 100644
--- a/backend/src/Designer/Services/Implementation/Preview/DataService.cs
+++ b/backend/src/Designer/Services/Implementation/Preview/DataService.cs
@@ -10,7 +10,7 @@ namespace Altinn.Studio.Designer.Services.Implementation.Preview;
public class DataService(
IDistributedCache distributedCache
- ) : IDataService
+) : IDataService
{
readonly DistributedCacheEntryOptions _cacheOptions = new()
{
diff --git a/backend/src/Designer/Services/Implementation/Preview/InstanceService.cs b/backend/src/Designer/Services/Implementation/Preview/InstanceService.cs
new file mode 100644
index 00000000000..adafb949868
--- /dev/null
+++ b/backend/src/Designer/Services/Implementation/Preview/InstanceService.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using Altinn.Platform.Storage.Interface.Models;
+using Altinn.Studio.Designer.Services.Interfaces.Preview;
+using Microsoft.Extensions.Caching.Distributed;
+
+namespace Altinn.Studio.Designer.Services.Implementation.Preview;
+
+public class InstanceService(
+ IDistributedCache distributedCache,
+ IDataService dataService
+) : IInstanceService
+{
+ readonly DistributedCacheEntryOptions _cacheOptions = new()
+ {
+ SlidingExpiration = TimeSpan.FromMinutes(30),
+ };
+
+ public Instance CreateInstance(string org, string app, int partyId, string taskId, List dataTypes)
+ {
+ Guid instanceGuid = Guid.NewGuid();
+ Instance instance = new()
+ {
+ InstanceOwner = new InstanceOwner { PartyId = partyId.ToString() },
+ Id = $"{instanceGuid}",
+ AppId = app,
+ Data = [],
+ Org = org,
+ Process = new ProcessState
+ {
+ CurrentTask = new ProcessElementInfo
+ {
+ AltinnTaskType = "data",
+ ElementId = taskId
+ }
+ }
+ };
+ dataTypes.ForEach(dataType =>
+ {
+ if (dataType.AppLogic?.AutoCreate == true)
+ {
+ DataElement dataElement = dataService.CreateDataElement(partyId, instanceGuid, dataType.Id);
+ instance.Data.Add(dataElement);
+ }
+ });
+ distributedCache.SetString(instance.Id, JsonSerializer.Serialize(instance), _cacheOptions);
+ return instance;
+ }
+
+ public Instance GetInstance(Guid instanceGuid)
+ {
+ string instanceJson = distributedCache.GetString(instanceGuid.ToString());
+ Instance instanceElement = JsonSerializer.Deserialize(instanceJson);
+ return instanceElement;
+ }
+
+ public Instance AddDataElement(Guid instanceGuid, DataElement dataElement)
+ {
+ string instanceJson = distributedCache.GetString(instanceGuid.ToString());
+ Instance instanceElement = JsonSerializer.Deserialize(instanceJson);
+ instanceElement.Data.Add(dataElement);
+ distributedCache.SetString(instanceGuid.ToString(), JsonSerializer.Serialize(instanceElement), _cacheOptions);
+ return instanceElement;
+ }
+
+ public Instance RemoveDataElement(Guid instanceGuid, Guid dataElementGuid)
+ {
+ string instanceJson = distributedCache.GetString(instanceGuid.ToString());
+ Instance instanceElement = JsonSerializer.Deserialize(instanceJson);
+ instanceElement.Data.RemoveAll(dataElement => dataElement.Id == dataElementGuid.ToString());
+ distributedCache.SetString(instanceGuid.ToString(), JsonSerializer.Serialize(instanceElement), _cacheOptions);
+ return instanceElement;
+ }
+}
diff --git a/backend/src/Designer/Services/Implementation/PreviewService.cs b/backend/src/Designer/Services/Implementation/PreviewService.cs
index aa88aec4e41..a8e07f8cd38 100644
--- a/backend/src/Designer/Services/Implementation/PreviewService.cs
+++ b/backend/src/Designer/Services/Implementation/PreviewService.cs
@@ -6,6 +6,7 @@
using Altinn.Platform.Storage.Interface.Models;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
+using Altinn.Studio.Designer.Models.App;
using Altinn.Studio.Designer.Services.Interfaces;
using LibGit2Sharp;
@@ -14,21 +15,17 @@ namespace Altinn.Studio.Designer.Services.Implementation;
///
/// Service for handling a mocked instance object for preview mode
///
-public class PreviewService : IPreviewService
+///
+/// Constructor
+///
+/// IAltinnGitRepository
+///
+public class PreviewService(IAltinnGitRepositoryFactory altinnGitRepositoryFactory) : IPreviewService
{
- private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory;
+ private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory = altinnGitRepositoryFactory;
public const string MockDataModelIdPrefix = "MockDataModel";
public const string MockDataTaskId = "test-datatask-id";
- ///
- /// Constructor
- ///
- /// IAltinnGitRepository
- public PreviewService(IAltinnGitRepositoryFactory altinnGitRepositoryFactory)
- {
- _altinnGitRepositoryFactory = altinnGitRepositoryFactory;
- }
-
///
public async Task GetMockInstance(string org, string app, string developer, int? instanceOwnerPartyId, string layoutSetName, CancellationToken cancellationToken = default)
{
@@ -133,27 +130,12 @@ private async Task> GetDataTypesForInstance(string org, string
AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
DataType dataType = await GetDataTypeForLayoutSetName(org, app, developer, layoutSetName);
string dataTypeForDataElement = shouldProcessActAsReceipt ? await GetDataTypeForCustomReceipt(altinnAppGitRepository) : dataType?.Id;
- if (dataTypeForDataElement is null && altinnAppGitRepository.AppUsesLayoutSets())
+ ApplicationMetadata applicationMetadata = await altinnAppGitRepository.GetApplicationMetadata();
+ List dataElements = applicationMetadata.DataTypes.Select(dataType => new DataElement
{
- int counter = 0;
- LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile();
- return layoutSets.Sets
- .Where(set => string.IsNullOrEmpty(set.DataType))
- .Select(_ => new DataElement
- {
- DataType = $"{MockDataModelIdPrefix}-{counter++}",
- Id = MockDataTaskId
- })
- .ToList();
- }
- return [
- // All data types attached to the current task in the process model should be added here
- new DataElement
- {
- DataType = dataTypeForDataElement,
- Id = MockDataTaskId
- }
- ];
+ Id = (dataTypeForDataElement != dataType.Id) ? dataType.Id : MockDataTaskId
+ }).ToList();
+ return dataElements;
}
private async Task GetDataTypeForCustomReceipt(AltinnAppGitRepository altinnAppGitRepository)
diff --git a/backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs b/backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs
index b35f8a8ccdb..3c01e869a16 100644
--- a/backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs
+++ b/backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs
@@ -95,7 +95,7 @@ public async Task GetTaskTypeFromProcessDefinition(AltinnRepoEditingCont
XmlSerializer serializer = new XmlSerializer(typeof(Definitions));
Definitions? definitions = (Definitions?)serializer.Deserialize(processDefinitionStream);
LayoutSetConfig layoutSet = await _appDevelopmentService.GetLayoutSetConfig(altinnRepoEditingContext, layoutSetId);
- string taskId = layoutSet.Tasks?.First();
+ string? taskId = layoutSet.Tasks?.First();
ProcessTask? task = definitions?.Process.Tasks.FirstOrDefault(task => task.Id == taskId);
return task?.ExtensionElements?.TaskExtension?.TaskType ?? string.Empty;
}
@@ -115,7 +115,12 @@ private Stream GetTemplateStream(SemanticVersion version, string templateName)
throw new FileNotFoundException("Unknown template.");
}
string template = templates.Single(template => template.EndsWith(templateName));
- return typeof(ProcessModelingService).Assembly.GetManifestResourceStream(template);
+ Stream? templateStream = typeof(ProcessModelingService).Assembly.GetManifestResourceStream(template);
+ if (templateStream == null)
+ {
+ throw new FileNotFoundException($"Template resource '{template}' not found in the assembly.");
+ }
+ return templateStream;
}
}
}
diff --git a/backend/src/Designer/Services/Implementation/SchemaModelService.cs b/backend/src/Designer/Services/Implementation/SchemaModelService.cs
index 3067a31d98d..556440a7e3c 100644
--- a/backend/src/Designer/Services/Implementation/SchemaModelService.cs
+++ b/backend/src/Designer/Services/Implementation/SchemaModelService.cs
@@ -40,6 +40,7 @@ public class SchemaModelService : ISchemaModelService
private readonly IXmlSchemaToJsonSchemaConverter _xmlSchemaToJsonSchemaConverter;
private readonly IJsonSchemaToXmlSchemaConverter _jsonSchemaToXmlSchemaConverter;
private readonly IModelMetadataToCsharpConverter _modelMetadataToCsharpConverter;
+ private readonly IApplicationMetadataService _applicationMetadataService;
///
/// Initializes a new instance of the class.
@@ -59,13 +60,15 @@ public class SchemaModelService : ISchemaModelService
///
/// Class for converting Json schemas to Xml schemas.
/// C# model generator
+ ///
public SchemaModelService(
IAltinnGitRepositoryFactory altinnGitRepositoryFactory,
ILoggerFactory loggerFactory,
ServiceRepositorySettings serviceRepositorySettings,
IXmlSchemaToJsonSchemaConverter xmlSchemaToJsonSchemaConverter,
IJsonSchemaToXmlSchemaConverter jsonSchemaToXmlSchemaConverter,
- IModelMetadataToCsharpConverter modelMetadataToCsharpConverter)
+ IModelMetadataToCsharpConverter modelMetadataToCsharpConverter,
+ IApplicationMetadataService applicationMetadataService)
{
_altinnGitRepositoryFactory = altinnGitRepositoryFactory;
_loggerFactory = loggerFactory;
@@ -73,6 +76,7 @@ public SchemaModelService(
_xmlSchemaToJsonSchemaConverter = xmlSchemaToJsonSchemaConverter;
_jsonSchemaToXmlSchemaConverter = jsonSchemaToXmlSchemaConverter;
_modelMetadataToCsharpConverter = modelMetadataToCsharpConverter;
+ _applicationMetadataService = applicationMetadataService;
}
///
@@ -431,5 +435,24 @@ private bool NamespaceNeedsToBeSeparated(ApplicationMetadata application,
{
return application.DataTypes.All(d => d.AppLogic?.ClassRef != $"Altinn.App.Models.{csharpModelName}");
}
+
+ public async Task GetModelDataType(string org, string app, string modelId)
+ {
+ ApplicationMetadata applicationMetadata = await _applicationMetadataService.GetApplicationMetadataFromRepository(org, app);
+ DataType dataType = applicationMetadata.DataTypes.Find((dataType) => dataType.Id == modelId);
+ return dataType;
+ }
+
+ public async Task SetModelDataType(string org, string app, string modelId, DataType dataType)
+ {
+ if (dataType.Id != modelId)
+ {
+ throw new ArgumentException("Provided modelId does not match the DataType's Id");
+ }
+ ApplicationMetadata applicationMetadata = await _applicationMetadataService.GetApplicationMetadataFromRepository(org, app);
+ applicationMetadata.DataTypes.RemoveAll((dt) => dt.Id == dataType.Id);
+ applicationMetadata.DataTypes.Add(dataType);
+ await _applicationMetadataService.UpdateApplicationMetaDataLocally(org, app, applicationMetadata);
+ }
}
}
diff --git a/backend/src/Designer/Services/Interfaces/IOptionsService.cs b/backend/src/Designer/Services/Interfaces/IOptionsService.cs
index 0a291a45819..74e31e12a97 100644
--- a/backend/src/Designer/Services/Interfaces/IOptionsService.cs
+++ b/backend/src/Designer/Services/Interfaces/IOptionsService.cs
@@ -2,6 +2,7 @@
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Models;
+using Altinn.Studio.Designer.Models.Dto;
using Microsoft.AspNetCore.Http;
namespace Altinn.Studio.Designer.Services.Interfaces;
@@ -31,6 +32,14 @@ public interface IOptionsService
/// The options list
public Task> GetOptionsList(string org, string repo, string developer, string optionsListId, CancellationToken cancellationToken = default);
+ ///
+ /// Gets a list of sources, , for all OptionListIds.
+ ///
+ /// An .
+ /// A that observes if operation is cancelled.
+ /// A list of
+ public Task> GetAllOptionListReferences(AltinnRepoEditingContext altinnRepoEditingContext, CancellationToken cancellationToken = default);
+
///
/// Creates a new options list in the app repository.
/// If the file already exists, it will be overwritten.
@@ -47,7 +56,7 @@ public interface IOptionsService
/// Adds a new option to the option list.
/// If the file already exists, it will be overwritten.
///
- /// Orginisation
+ /// Organisation
/// Repository
/// Username of developer
/// Name of the new options list
diff --git a/backend/src/Designer/Services/Interfaces/ISchemaModelService.cs b/backend/src/Designer/Services/Interfaces/ISchemaModelService.cs
index c043f7fa8cd..16cc0a91f34 100644
--- a/backend/src/Designer/Services/Interfaces/ISchemaModelService.cs
+++ b/backend/src/Designer/Services/Interfaces/ISchemaModelService.cs
@@ -84,5 +84,15 @@ public interface ISchemaModelService
/// An that observes if operation is cancelled.
/// Returns the model metadata
Task GenerateModelMetadataFromJsonSchema(AltinnRepoEditingContext altinnRepoEditingContext, string relativeFilePath, CancellationToken cancellationToken = default);
+
+ ///
+ /// Gets the dataType for a given model.
+ ///
+ Task GetModelDataType(string org, string app, string modelId);
+
+ ///
+ /// Updates the dataType for a given model.
+ ///
+ Task SetModelDataType(string org, string app, string modelId, DataType dataType);
}
}
diff --git a/backend/src/Designer/Services/Interfaces/Preview/IDataService.cs b/backend/src/Designer/Services/Interfaces/Preview/IDataService.cs
index e12c80a05bf..ac60a9db279 100644
--- a/backend/src/Designer/Services/Interfaces/Preview/IDataService.cs
+++ b/backend/src/Designer/Services/Interfaces/Preview/IDataService.cs
@@ -11,6 +11,7 @@ namespace Altinn.Studio.Designer.Services.Interfaces.Preview;
public interface IDataService
{
public DataElement CreateDataElement(int partyId, Guid instanceGuid, string dataTypeId);
+
public JsonNode GetDataElement(Guid dataGuid);
public JsonNode PatchDataElement(Guid dataGuid, JsonPatch patch);
}
diff --git a/backend/src/Designer/Services/Interfaces/Preview/IInstanceService.cs b/backend/src/Designer/Services/Interfaces/Preview/IInstanceService.cs
new file mode 100644
index 00000000000..9567f420e33
--- /dev/null
+++ b/backend/src/Designer/Services/Interfaces/Preview/IInstanceService.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using Altinn.Platform.Storage.Interface.Models;
+
+namespace Altinn.Studio.Designer.Services.Interfaces.Preview;
+
+///
+/// Interface for handling a mocked datatype object for preview mode
+///
+public interface IInstanceService
+{
+ public Instance CreateInstance(string org, string app, int partyId, string taskId, List dataTypes);
+ public Instance GetInstance(Guid instanceGuid);
+
+ public Instance AddDataElement(Guid instanceGuid, DataElement dataElement);
+ public Instance RemoveDataElement(Guid instanceGuid, Guid dataElementGuid);
+}
diff --git a/backend/src/Designer/TypedHttpClients/Altinn2Metadata/Altinn2MetadataClient.cs b/backend/src/Designer/TypedHttpClients/Altinn2Metadata/Altinn2MetadataClient.cs
index 29cf2b5373f..2eda4ef7783 100644
--- a/backend/src/Designer/TypedHttpClients/Altinn2Metadata/Altinn2MetadataClient.cs
+++ b/backend/src/Designer/TypedHttpClients/Altinn2Metadata/Altinn2MetadataClient.cs
@@ -57,7 +57,7 @@ public async Task GetXacmlPolicy(string serviceCode, int serviceEdi
public async Task> AvailableServices(int languageId, string environment)
{
- List? availableServices = null;
+ List availableServices = null;
string bridgeBaseUrl = GetSblBridgeUrl(environment);
string availabbleServicePath = $"{bridgeBaseUrl}metadata/api/availableServices?languageID={languageId}&appTypesToInclude=0&includeExpired=false";
diff --git a/backend/src/Designer/TypedHttpClients/AzureDevOps/AzureDevOpsBuildClient.cs b/backend/src/Designer/TypedHttpClients/AzureDevOps/AzureDevOpsBuildClient.cs
index 5ea2f691e15..f87b31ec4a1 100644
--- a/backend/src/Designer/TypedHttpClients/AzureDevOps/AzureDevOpsBuildClient.cs
+++ b/backend/src/Designer/TypedHttpClients/AzureDevOps/AzureDevOpsBuildClient.cs
@@ -30,6 +30,7 @@ public class AzureDevOpsBuildClient : IAzureDevOpsBuildClient
/// GeneralSettings
/// ISourceControl
/// ILogger
+ /// The http context accessor.
public AzureDevOpsBuildClient(
HttpClient httpClient,
GeneralSettings generalSettingsOptions,
diff --git a/backend/tests/DataModeling.Tests/DataModeling.Tests.csproj b/backend/tests/DataModeling.Tests/DataModeling.Tests.csproj
index 74c99c7cc08..a1dbd2fb83b 100644
--- a/backend/tests/DataModeling.Tests/DataModeling.Tests.csproj
+++ b/backend/tests/DataModeling.Tests/DataModeling.Tests.csproj
@@ -5,7 +5,6 @@
-
diff --git a/backend/tests/Designer.Tests/Controllers/AnsattPortenController/AuthStatusTests.cs b/backend/tests/Designer.Tests/Controllers/AnsattPortenController/AuthStatusTests.cs
index 59958508764..cb44ab9b2b6 100644
--- a/backend/tests/Designer.Tests/Controllers/AnsattPortenController/AuthStatusTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/AnsattPortenController/AuthStatusTests.cs
@@ -1,3 +1,4 @@
+using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
@@ -67,7 +68,7 @@ public async Task AuthStatus_Should_ReturnTrue_IfAuthenticated()
{
services.AddAuthentication(defaultScheme: TestAuthConstants.TestAuthenticationScheme)
.AddScheme(
- TestAuthConstants.TestAuthenticationScheme, options => { });
+ TestAuthConstants.TestAuthenticationScheme, options => { options.TimeProvider = TimeProvider.System; });
services.AddTransient();
};
diff --git a/backend/tests/Designer.Tests/Controllers/ApiTests/ApiTestsBase.cs b/backend/tests/Designer.Tests/Controllers/ApiTests/ApiTestsBase.cs
index 7b03c34ac9e..0a4908f1c82 100644
--- a/backend/tests/Designer.Tests/Controllers/ApiTests/ApiTestsBase.cs
+++ b/backend/tests/Designer.Tests/Controllers/ApiTests/ApiTestsBase.cs
@@ -94,7 +94,8 @@ protected virtual HttpClient GetTestClient()
{
services.AddAuthentication(defaultScheme: TestAuthConstants.TestAuthenticationScheme)
.AddScheme(
- TestAuthConstants.TestAuthenticationScheme, options => { });
+ TestAuthConstants.TestAuthenticationScheme,
+ options => { options.TimeProvider = TimeProvider.System; });
services.AddTransient();
});
builder.ConfigureServices(ConfigureTestServicesForSpecificTest);
diff --git a/backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandler.cs b/backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandler.cs
index d510b1d5af6..8139d1c4f28 100644
--- a/backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandler.cs
+++ b/backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandler.cs
@@ -1,3 +1,4 @@
+using System;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
@@ -10,8 +11,8 @@ namespace Designer.Tests.Controllers.ApiTests;
public class TestAuthHandler : AuthenticationHandler
{
public TestAuthHandler(IOptionsMonitor options,
- ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
- : base(options, logger, encoder, clock)
+ ILoggerFactory logger, UrlEncoder encoder)
+ : base(options, logger, encoder)
{
}
diff --git a/backend/tests/Designer.Tests/Controllers/DataModelsController/GetTests.cs b/backend/tests/Designer.Tests/Controllers/DataModelsController/GetTests.cs
index bac7b5943e7..31c013aa15f 100644
--- a/backend/tests/Designer.Tests/Controllers/DataModelsController/GetTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/DataModelsController/GetTests.cs
@@ -1,6 +1,9 @@
-using System.Net;
+using System.Collections.Generic;
+using System.Net;
using System.Net.Http;
+using System.Net.Http.Json;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Designer.Tests.Controllers.ApiTests;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
@@ -26,4 +29,42 @@ public async Task GetDatamodel_ValidPath_ShouldReturnContent(string modelPath, s
using var response = await HttpClient.SendAsync(httpRequestMessage);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
+
+ [Theory]
+ [InlineData("Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES", "ttd", "hvem-er-hvem")]
+ public async Task GetDatamodelDataType_ShouldReturnContent(string modelName, string org, string repo)
+ {
+ string url = $"{VersionPrefix(org, repo)}/datamodel/{modelName}/dataType";
+ using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ DataType dataTypeResponse = await response.Content.ReadFromJsonAsync();
+ dataTypeResponse.Should().NotBeNull();
+ dataTypeResponse.Should().BeEquivalentTo(new DataType
+ {
+ Id = "Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES",
+ AllowedContentTypes = new List { "application/xml" },
+ AppLogic = new ApplicationLogic
+ {
+ AutoCreate = true,
+ ClassRef = "Altinn.App.Models.HvemErHvem_M"
+ },
+ TaskId = "Task_1",
+ MaxCount = 1,
+ MinCount = 1
+ });
+ }
+
+ [Theory]
+ [InlineData("notfound", "ttd", "hvem-er-hvem")]
+ public async Task GetDatamodelDataType_ShouldNullWhenNotFound(string modelName, string org, string repo)
+ {
+ string url = $"{VersionPrefix(org, repo)}/datamodel/{modelName}/dataType";
+ using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ (await response.Content.ReadAsStringAsync()).Should().Be("null");
+ }
}
diff --git a/backend/tests/Designer.Tests/Controllers/DataModelsController/PutDatamodelTests.cs b/backend/tests/Designer.Tests/Controllers/DataModelsController/PutDatamodelTests.cs
index 0ee22606477..4db5c7cf72f 100644
--- a/backend/tests/Designer.Tests/Controllers/DataModelsController/PutDatamodelTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/DataModelsController/PutDatamodelTests.cs
@@ -4,6 +4,7 @@
using System.Linq;
using System.Net;
using System.Net.Http;
+using System.Net.Http.Json;
using System.Net.Mime;
using System.Text;
using System.Text.Json;
@@ -11,6 +12,7 @@
using System.Web;
using System.Xml;
using System.Xml.Schema;
+using Altinn.Platform.Storage.Interface.Models;
using Altinn.Studio.DataModeling.Converter.Json;
using Altinn.Studio.DataModeling.Converter.Json.Strategy;
using Altinn.Studio.DataModeling.Converter.Metadata;
@@ -144,6 +146,54 @@ public async Task IncompatibleSchema_ShouldReturn422(string modelPath, string sc
}
}
+ [Theory]
+ [InlineData("testmodelname", "ttd", "hvem-er-hvem")]
+ public async Task PutDatamodelDataType_ShouldReturnWithoutErrors(string datamodelName, string org, string repo)
+ {
+ string url = $"{VersionPrefix(org, TargetTestRepository)}/datamodel/{datamodelName}/dataType";
+ await CopyRepositoryForTest(org, repo, "testUser", TargetTestRepository);
+
+ DataType dataType = new()
+ {
+ Id = datamodelName,
+ MaxCount = 1,
+ MinCount = 1,
+ };
+ using var putRequest = new HttpRequestMessage(HttpMethod.Put, url)
+ {
+ Content = JsonContent.Create(dataType)
+ };
+
+ HttpResponseMessage response = await HttpClient.SendAsync(putRequest);
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ DataType dataTypeResponse = await response.Content.ReadFromJsonAsync();
+ dataTypeResponse.Should().NotBeNull();
+ dataTypeResponse.Should().BeEquivalentTo(dataType);
+ }
+
+ [Theory]
+ [InlineData("testmodelname", "ttd", "hvem-er-hvem")]
+ public async Task PutDatamodelDataType_FailsIfDatamodelNameMismatchesObjectId(string datamodelName, string org, string repo)
+ {
+ string url = $"{VersionPrefix(org, TargetTestRepository)}/datamodel/{datamodelName}/dataType";
+ await CopyRepositoryForTest(org, repo, "testUser", TargetTestRepository);
+
+ DataType dataType = new()
+ {
+ Id = "wrongId",
+ MaxCount = 1,
+ MinCount = 1,
+ };
+ using var putRequest = new HttpRequestMessage(HttpMethod.Put, url)
+ {
+ Content = JsonContent.Create(dataType)
+ };
+
+ HttpResponseMessage response = await HttpClient.SendAsync(putRequest);
+ response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
+ }
+
+
private async Task FilesWithCorrectNameAndContentShouldBeCreated(string modelName)
{
var location = Path.GetFullPath(Path.Combine(TestRepoPath, "App", "models"));
diff --git a/backend/tests/Designer.Tests/Controllers/OptionsController/GetOptionListsReferencesTests.cs b/backend/tests/Designer.Tests/Controllers/OptionsController/GetOptionListsReferencesTests.cs
new file mode 100644
index 00000000000..d4fdd5d11db
--- /dev/null
+++ b/backend/tests/Designer.Tests/Controllers/OptionsController/GetOptionListsReferencesTests.cs
@@ -0,0 +1,88 @@
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Altinn.Studio.Designer.Models.Dto;
+using Designer.Tests.Controllers.ApiTests;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace Designer.Tests.Controllers.OptionsController;
+
+public class GetOptionListsReferencesTests : DesignerEndpointsTestsBase, IClassFixture>
+{
+ const string RepoWithUsedOptions = "app-with-options";
+ const string RepoWithUnusedOptions = "app-with-layoutsets";
+
+ public GetOptionListsReferencesTests(WebApplicationFactory factory) : base(factory)
+ {
+ }
+
+ [Fact]
+ public async Task GetOptionListsReferences_Returns200OK_WithValidOptionsReferences()
+ {
+ string apiUrl = $"/designer/api/ttd/{RepoWithUsedOptions}/options/usage";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, apiUrl);
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ string responseBody = await response.Content.ReadAsStringAsync();
+ List responseList = JsonSerializer.Deserialize>(responseBody);
+
+ List expectedResponseList = new()
+ {
+ new RefToOptionListSpecifier
+ {
+ OptionListId = "test-options", OptionListIdSources =
+ [
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-same-options-id-in-same-set-and-another-layout"],
+ LayoutName = "layoutWithOneOptionListIdRef.json",
+ LayoutSetId = "layoutSet1"
+ },
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-test-options-id", "component-using-test-options-id-again"],
+ LayoutName = "layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json",
+ LayoutSetId = "layoutSet1"
+ },
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-same-options-id-in-another-set"],
+ LayoutName = "layoutWithTwoOptionListIdRefs.json",
+ LayoutSetId = "layoutSet2"
+ }
+ ]
+ },
+ new()
+ {
+ OptionListId = "other-options", OptionListIdSources =
+ [
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-other-options-id"],
+ LayoutName = "layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json",
+ LayoutSetId = "layoutSet1"
+ }
+ ]
+ }
+ };
+
+ Assert.Equal(StatusCodes.Status200OK, (int)response.StatusCode);
+ Assert.Equivalent(expectedResponseList, responseList);
+ }
+
+ [Fact]
+ public async Task GetOptionListsReferences_Returns200Ok_WithEmptyOptionsReferences_WhenLayoutsDoesNotReferenceAnyOptionsInApp()
+ {
+ string apiUrl = $"/designer/api/ttd/{RepoWithUnusedOptions}/options/usage";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, apiUrl);
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ string responseBody = await response.Content.ReadAsStringAsync();
+
+ Assert.Equal(StatusCodes.Status200OK, (int)response.StatusCode);
+ Assert.Equivalent("[]", responseBody);
+ }
+}
diff --git a/backend/tests/Designer.Tests/Controllers/Preview/DataControllerTests.cs b/backend/tests/Designer.Tests/Controllers/Preview/DataControllerTests.cs
new file mode 100644
index 00000000000..468c73aa4d3
--- /dev/null
+++ b/backend/tests/Designer.Tests/Controllers/Preview/DataControllerTests.cs
@@ -0,0 +1,123 @@
+using System.Net;
+using System.Net.Http;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
+using Altinn.Studio.Designer.Models.Preview;
+using Designer.Tests.Controllers.PreviewController;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace Designer.Tests.Controllers.Preview;
+
+public class DataControllerTests(WebApplicationFactory factory) : PreviewControllerTestsBase(factory), IClassFixture>
+{
+ [Fact]
+ public async Task Post_ReturnsCreated()
+ {
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+
+ string responseBody = await response.Content.ReadAsStringAsync();
+ DataElement dataElement = JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
+ Assert.NotNull(dataElement.Id);
+ Assert.Equal(instance.Id, dataElement.InstanceGuid);
+ }
+
+ [Fact]
+ public async Task Get_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "datamodel");
+
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}";
+ using HttpRequestMessage httpRequestMessageGet = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage responseGet = await HttpClient.SendAsync(httpRequestMessageGet);
+ Assert.Equal(HttpStatusCode.OK, responseGet.StatusCode);
+ string responseBodyGet = await responseGet.Content.ReadAsStringAsync();
+ JsonNode dataItem = JsonSerializer.Deserialize(responseBodyGet, JsonSerializerOptions);
+ Assert.NotNull(dataItem);
+ }
+
+ [Fact]
+ public async Task Patch_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "datamodel");
+
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}";
+ using HttpRequestMessage httpRequestMessagePatch = new(HttpMethod.Patch, dataPath);
+
+ string patch = "{\"patch\":[{\"op\":\"add\",\"path\":\"/RegNo\",\"value\":\"asdf\"}],\"ignoredValidators\":[\"DataAnnotations\",\"Required\",\"Expression\"]}";
+ httpRequestMessagePatch.Content = new StringContent(patch, System.Text.Encoding.UTF8, "application/json");
+ using HttpResponseMessage responsePatch = await HttpClient.SendAsync(httpRequestMessagePatch);
+ Assert.Equal(HttpStatusCode.OK, responsePatch.StatusCode);
+ string responseBodyPatch = await responsePatch.Content.ReadAsStringAsync();
+ JsonNode dataItem = JsonSerializer.Deserialize(responseBodyPatch, JsonSerializerOptions);
+ Assert.NotNull(dataItem);
+ Assert.Equal("asdf", dataItem["newDataModel"]["RegNo"].ToString());
+ }
+
+ [Fact]
+ public async Task PatchMultiple_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement1 = await createDataElement(instance, "datamodel");
+ DataElement dataElement2 = await createDataElement(instance, "datamodel");
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data";
+ using HttpRequestMessage httpRequestMessagePatchMultiple = new(HttpMethod.Patch, dataPath);
+
+ string patches = "{\"patches\":[{\"dataElementId\":\"" + dataElement1.Id + "\",\"patch\":[{\"op\":\"add\",\"path\":\"/RegNo\",\"value\":\"dataobj1\"}]},{\"dataElementId\":\"" + dataElement2.Id + "\",\"patch\":[{\"op\":\"add\",\"path\":\"/RegNo\",\"value\":\"dataobj2\"}]}],\"ignoredValidators\":[\"DataAnnotations\",\"Required\",\"Expression\"]}";
+ httpRequestMessagePatchMultiple.Content = new StringContent(patches, System.Text.Encoding.UTF8, "application/json");
+ using HttpResponseMessage responsePatchMultiple = await HttpClient.SendAsync(httpRequestMessagePatchMultiple);
+ Assert.Equal(HttpStatusCode.OK, responsePatchMultiple.StatusCode);
+ string responseBodyPatchMultiple = await responsePatchMultiple.Content.ReadAsStringAsync();
+ DataPatchResponseMultiple dataItem = JsonSerializer.Deserialize(responseBodyPatchMultiple, JsonSerializerOptions);
+ Assert.NotNull(dataItem);
+ Assert.Equal(2, dataItem.NewDataModels.Count);
+ object dataItem1 = JsonSerializer.Serialize(dataItem.NewDataModels[0].Data);
+ Assert.Equal("{\"RegNo\":\"dataobj1\"}", dataItem1.ToString());
+ object dataItem2 = JsonSerializer.Serialize(dataItem.NewDataModels[1].Data);
+ Assert.Equal("{\"RegNo\":\"dataobj2\"}", dataItem2.ToString());
+ }
+
+ [Fact]
+ public async Task Delete_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "datamodel");
+
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}";
+ using HttpRequestMessage httpRequestMessageDelete = new(HttpMethod.Delete, dataPath);
+ using HttpResponseMessage responseDelete = await HttpClient.SendAsync(httpRequestMessageDelete);
+ Assert.Equal(HttpStatusCode.OK, responseDelete.StatusCode);
+ }
+
+ [Fact]
+ public async Task Validate_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "datamodel");
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}/validate";
+ using HttpRequestMessage httpRequestMessageValidate = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage responseValidate = await HttpClient.SendAsync(httpRequestMessageValidate);
+ Assert.Equal(HttpStatusCode.OK, responseValidate.StatusCode);
+ }
+
+ [Fact]
+ public async Task Tag_ReturnsCreateOkd()
+ {
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "datamodel");
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}/tags";
+ using HttpRequestMessage httpRequestMessageTag = new(HttpMethod.Post, dataPath);
+ httpRequestMessageTag.Content = new StringContent("{\"tag\":\"test\"}", System.Text.Encoding.UTF8, "application/json");
+ using HttpResponseMessage responseTag = await HttpClient.SendAsync(httpRequestMessageTag);
+ Assert.Equal(HttpStatusCode.Created, responseTag.StatusCode);
+ }
+}
diff --git a/backend/tests/Designer.Tests/Controllers/Preview/InstancesControllerTests.cs b/backend/tests/Designer.Tests/Controllers/Preview/InstancesControllerTests.cs
new file mode 100644
index 00000000000..716770b3e7d
--- /dev/null
+++ b/backend/tests/Designer.Tests/Controllers/Preview/InstancesControllerTests.cs
@@ -0,0 +1,71 @@
+using System.Net;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
+using Designer.Tests.Controllers.PreviewController;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace Designer.Tests.Controllers.Preview;
+
+public class InstancesControllerTests(
+ WebApplicationFactory factory
+) : PreviewControllerTestsBase(factory), IClassFixture>
+{
+
+ [Fact]
+ public async Task Post_ReturnsCreated()
+ {
+ Instance instance = await createInstance();
+ Assert.NotNull(instance);
+ Assert.NotNull(instance.Id);
+ }
+
+ [Fact]
+ public async Task GetInstance_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ Assert.NotNull(instance);
+ Assert.NotNull(instance.Id);
+
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ string responseBody = await response.Content.ReadAsStringAsync();
+ Instance responseInstance = JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
+ Assert.NotNull(responseInstance);
+ Assert.Equal(instance.Id, responseInstance.Id);
+ }
+
+ [Fact]
+ public async Task Validate_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/validate";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+
+ [Fact]
+ public async Task Process_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/process";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+
+ [Fact]
+ public async Task ProcessNext_ReturnsOk()
+ {
+ Instance instance = await createInstance();
+ string dataPath = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/process/next";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPath);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/AnonymousTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/AnonymousTests.cs
index ae21b0c033d..f3accf4071a 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/AnonymousTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/AnonymousTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
@@ -17,8 +18,9 @@ public AnonymousTests(WebApplicationFactory factory) : base(factory)
[Fact]
public async Task Get_Anonymous_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/v1/data/anonymous";
+ string dataPathWithData = $"{Org}/{AppV4}/api/v1/data/anonymous";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/ApplicationMetadataTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/ApplicationMetadataTests.cs
index 3671a2b4747..c8ecc70b75d 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/ApplicationMetadataTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/ApplicationMetadataTests.cs
@@ -78,42 +78,6 @@ public async Task Get_ApplicationMetadata_With_V8_Altinn_Nuget_Version_Ok()
JsonUtils.DeepEquals(expectedJson, responseBody).Should().BeTrue();
}
- [Fact]
- public async Task Get_ApplicationMetadata_WithLessDataTypesThanLayoutSetsFile_OkWithMockedDataTypes()
- {
- string expectedApplicationMetadataString = TestDataHelper.GetFileFromRepo(Org, AppV4, Developer, "App/config/applicationmetadata.json");
- _appDevelopmentServiceMock
- .Setup(rs => rs.GetAppLibVersion(It.IsAny()))
- .Returns(NuGet.Versioning.NuGetVersion.Parse("8.0.0"));
-
- string dataPathWithData = $"{Org}/{AppV4}/api/v1/applicationmetadata";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- ApplicationMetadata expectedApplicationMetadata = JsonSerializer.Deserialize(expectedApplicationMetadataString, JsonSerializerOptions);
- expectedApplicationMetadata.AltinnNugetVersion = "8.0.0.0";
- // Add the mocked data type to expected app metadata
- expectedApplicationMetadata.DataTypes.Add(new DataType()
- {
- Id = $"{PreviewService.MockDataModelIdPrefix}-0",
- AppLogic = new ApplicationLogic()
- {
- ClassRef = $"Altinn.App.Models.model.{PreviewService.MockDataModelIdPrefix}-0"
- },
- TaskId = "Task_2"
- });
- expectedApplicationMetadata.PartyTypesAllowed.Person = false;
- expectedApplicationMetadata.PartyTypesAllowed.Organisation = false;
- expectedApplicationMetadata.PartyTypesAllowed.SubUnit = false;
- expectedApplicationMetadata.PartyTypesAllowed.BankruptcyEstate = false;
-
- string expectedJson = JsonSerializer.Serialize(expectedApplicationMetadata, JsonSerializerOptions);
- JsonUtils.DeepEquals(expectedJson, responseBody).Should().BeTrue();
- }
-
[Fact]
public async Task Get_ApplicationMetadata_WithAllPartyTypesAllowedSetToFalse()
{
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentPartyTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentPartyTests.cs
index d9d092d6da8..fae557ab685 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentPartyTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentPartyTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
@@ -19,8 +20,9 @@ public CurrentPartyTests(WebApplicationFactory factory) : base(factory)
[Fact]
public async Task Get_CurrentParty_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/authorization/parties/current";
+ string dataPathWithData = $"{Org}/{AppV4}/api/authorization/parties/current";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentUserTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentUserTests.cs
index 0836a9c485d..de858d8e7d7 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentUserTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/CurrentUserTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
@@ -19,8 +20,9 @@ public CurrentUserTests(WebApplicationFactory factory) : base(factory)
[Fact]
public async Task Get_CurrentUser_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/v1/profile/user";
+ string dataPathWithData = $"{Org}/{AppV4}/api/v1/profile/user";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/DeleteAttachmentTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/DeleteAttachmentTests.cs
index 3f0ff5e14c1..fd946cee59d 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/DeleteAttachmentTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/DeleteAttachmentTests.cs
@@ -2,6 +2,7 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
@@ -17,9 +18,9 @@ public DeleteAttachmentTests(WebApplicationFactory factory) : base(fact
[Fact]
public async Task Delete_Attachment_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/data/{AttachmentGuId}";
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{V3InstanceId}/data/asdf";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Delete, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3Path}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@@ -28,9 +29,10 @@ public async Task Delete_Attachment_Ok()
[Fact]
public async Task Delete_AttachmentForV4App_Ok()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/data/{AttachmentGuId}";
+ Instance instance = await createInstance();
+ DataElement dataElement = await createDataElement(instance, "attachment");
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data/{dataElement.Id}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Delete, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/GetFooterTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/GetFooterTests.cs
index ee391e0371f..23d979706af 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/GetFooterTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/GetFooterTests.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using System.Net;
using System.Net.Http;
@@ -35,18 +36,5 @@ public async Task Get_Footer_Exists_Ok()
responseFooterFile.Footer.Should().BeEquivalentTo(actualFooterFile.Footer);
}
-
- [Fact]
- public async Task Get_Footer_Non_Existing_Ok()
- {
- string dataPathWithData = $"{Org}/{AppV3}/api/v1/footer";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseString = await response.Content.ReadAsStringAsync();
- responseString.Should().BeEmpty();
- }
}
}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/GetFormDataTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/GetFormDataTests.cs
deleted file mode 100644
index eae40b51eb8..00000000000
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/GetFormDataTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Designer.Tests.Utils;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using SharedResources.Tests;
-using Xunit;
-
-namespace Designer.Tests.Controllers.PreviewController
-{
- public class GetFormDataTests : PreviewControllerTestsBase, IClassFixture>
- {
-
- public GetFormDataTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
- [Fact]
- public async Task Get_FormData_Ok()
- {
- string expectedFormData = TestDataHelper.GetFileFromRepo(Org, PreviewApp, Developer, "App/models/custom-dm-name.schema.json");
-
- string dataPathWithData = $"{Org}/{PreviewApp}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={PreviewApp}&selectedLayoutSet=");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- JsonUtils.DeepEquals(expectedFormData, responseBody).Should().BeTrue();
- }
-
- [Fact]
- public async Task Get_FormDataForAppWithoutDatamodel_Ok()
- {
- string dataPathWithData = $"{Org}/empty-app/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- responseBody.Should().Be($"{PartyId}/{InstanceGuId}");
- }
-
- [Fact]
- public async Task Get_FormDataForV4App_Ok()
- {
- string expectedFormData = TestDataHelper.GetFileFromRepo(Org, AppV4, Developer, "App/models/datamodel.schema.json");
-
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- JsonUtils.DeepEquals(expectedFormData, responseBody).Should().BeTrue();
- }
-
- [Fact]
- public async Task Get_FormDataForV4AppForTaskWithoutDatamodel_Ok()
- {
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName2}");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- responseBody.Should().Be($"{PartyId}/{InstanceGuId}");
- }
- }
-}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/GetImageTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/GetImageTests.cs
index e314dfb04bb..45d1ff5e68b 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/GetImageTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/GetImageTests.cs
@@ -65,7 +65,7 @@ public async Task Get_Image_From_Sub_Sub_Folder_Ok()
[Fact]
public async Task Get_Image_Non_Existing_Folder_Returns_NotFound()
{
- string dataPathWithData = $"{Org}/{AppV3}/images/subImagesFolder/SubSubImageFolder/AltinnD-logo.svg";
+ string dataPathWithData = $"{Org}/{AppV3Path}/images/subImagesFolder/SubSubImageFolder/AltinnD-logo.svg";
using HttpResponseMessage response = await HttpClient.GetAsync(dataPathWithData);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
@@ -74,7 +74,7 @@ public async Task Get_Image_Non_Existing_Folder_Returns_NotFound()
[Fact]
public async Task Get_Image_Non_Existing_Image_Return_NotFound()
{
- string dataPathWithData = $"{Org}/{AppV3}/images/subImagesFolder/non-existing-image.svg";
+ string dataPathWithData = $"{Org}/{AppV3Path}/images/subImagesFolder/non-existing-image.svg";
using HttpResponseMessage response = await HttpClient.GetAsync(dataPathWithData);
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/GetOptionsTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/GetOptionsTests.cs
index 22c3bb7d419..82c8ebc04e7 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/GetOptionsTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/GetOptionsTests.cs
@@ -1,7 +1,9 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
@@ -31,7 +33,8 @@ public async Task Get_Options_when_options_exists_Ok()
[Fact]
public async Task Get_Options_when_options_exists_for_v4_app_Ok()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/options/test-options";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/options/test-options";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
@@ -45,8 +48,9 @@ public async Task Get_Options_when_options_exists_for_v4_app_Ok()
[Fact]
public async Task Get_Options_when_no_options_exist_returns_Ok_empty_list()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/options/non-existing-options";
+ string dataPathWithData = $"{Org}/{AppV4}/api/options/non-existing-options";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/GetRuleHandlerTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/GetRuleHandlerTests.cs
index 70f2f7c04b0..cfb2f4b7ac6 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/GetRuleHandlerTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/GetRuleHandlerTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Testing;
@@ -16,8 +17,9 @@ public GetRuleHandlerTests(WebApplicationFactory factory) : base(factor
[Fact]
public async Task Get_RuleHandler_NoContent()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/resource/RuleHandler.js";
+ string dataPathWithData = $"{Org}/{AppV4}/api/resource/RuleHandler.js";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/InstanceForNextTaskTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/InstanceForNextTaskTests.cs
index c751bfaa0c9..061c1ec8904 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/InstanceForNextTaskTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/InstanceForNextTaskTests.cs
@@ -10,46 +10,41 @@
namespace Designer.Tests.Controllers.PreviewController
{
- public class InstanceForNextTaskTests : PreviewControllerTestsBase, IClassFixture>
+ public class InstanceForNextTaskTests(WebApplicationFactory factory) : PreviewControllerTestsBase(factory), IClassFixture>
{
-
- public InstanceForNextTaskTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
[Fact]
public async Task Get_InstanceForNextProcess_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}";
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{V3InstanceId}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3Path}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
string responseBody = await response.Content.ReadAsStringAsync();
JsonDocument responseDocument = JsonDocument.Parse(responseBody);
- Instance instance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
- Assert.Equal($"{PartyId}/{InstanceGuId}", instance.Id);
- Assert.Equal("ttd", instance.Org);
+ Instance responseInstance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
+ Assert.Equal(PartyId + "/" + V3InstanceId, responseInstance.Id);
+ Assert.Equal(Org, responseInstance.Org);
}
[Fact]
public async Task Get_InstanceForNextTaskForV4App_Ok_TaskIsIncreased()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
string responseBody = await response.Content.ReadAsStringAsync();
JsonDocument responseDocument = JsonDocument.Parse(responseBody);
- Instance instance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
- Assert.Equal($"{PartyId}/{InstanceGuId}", instance.Id);
- Assert.Equal("ttd", instance.Org);
- Assert.Equal("Task_1", instance.Process.CurrentTask.ElementId);
+ Instance responseInstance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
+ Assert.Equal(instance.Id, responseInstance.Id);
+ Assert.Equal(Org, responseInstance.Org);
+ Assert.Equal(TaskId, instance.Process.CurrentTask.ElementId);
}
}
}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/InstancesTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/InstancesTests.cs
deleted file mode 100644
index bbd1977ab98..00000000000
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/InstancesTests.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Altinn.Platform.Storage.Interface.Models;
-using Designer.Tests.Utils;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Newtonsoft.Json;
-using Xunit;
-
-namespace Designer.Tests.Controllers.PreviewController
-{
- public class InstancesTests : PreviewControllerTestsBase, IClassFixture>
- {
-
- public InstancesTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
- [Fact]
- public async Task Post_Instance_Ok()
- {
- string targetRepository = TestDataHelper.GenerateTestRepoName();
- await CopyRepositoryForTest(Org, AppV3, Developer, targetRepository);
-
- string dataPathWithData = $"{Org}/{targetRepository}/instances?instanceOwnerPartyId=51001";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- JsonDocument responseDocument = JsonDocument.Parse(responseBody);
- Instance instance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
- Assert.Equal("test-datatask-id", instance.Data[0].Id);
- Assert.Equal("Task_1", instance.Process.CurrentTask.ElementId);
- }
-
- [Fact]
- public async Task Post_InstanceForV4App_Ok()
- {
- string targetRepository = TestDataHelper.GenerateTestRepoName();
- await CopyRepositoryForTest(Org, AppV4, Developer, targetRepository);
-
- string dataPathWithData = $"{Org}/{targetRepository}/instances?instanceOwnerPartyId=51001";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- JsonDocument responseDocument = JsonDocument.Parse(responseBody);
- Instance instance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
- Assert.Equal("test-datatask-id", instance.Data[0].Id);
- Assert.Equal("Task_1", instance.Process.CurrentTask.ElementId);
- }
-
- [Fact]
- public async Task Post_InstanceForCustomReceipt_Ok()
- {
- string targetRepository = TestDataHelper.GenerateTestRepoName();
- await CopyRepositoryForTest(Org, AppV4, Developer, targetRepository);
-
- string dataPathWithData = $"{Org}/{targetRepository}/instances?instanceOwnerPartyId=51001";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={CustomReceiptLayoutSetName}");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- JsonDocument responseDocument = JsonDocument.Parse(responseBody);
- Instance instance = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
- Assert.Equal(CustomReceiptDataType, instance.Data[0].DataType);
- Assert.Equal("EndEvent_1", instance.Process.EndEvent);
- instance.Process.CurrentTask.Should().BeNull();
- }
- }
-}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/KeepAliveTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/KeepAliveTests.cs
index 2b70f87910c..0eb818f3827 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/KeepAliveTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/KeepAliveTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Testing;
@@ -16,8 +17,9 @@ public KeepAliveTests(WebApplicationFactory factory) : base(factory)
[Fact]
public async Task Get_KeepAlive_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/authentication/keepAlive";
+ string dataPathWithData = $"{Org}/{AppV4}/api/authentication/keepAlive";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSetsTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSetsTests.cs
index 10d693b8af9..9f171ef582f 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSetsTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSetsTests.cs
@@ -1,12 +1,8 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
-using System.Text.Json;
using System.Threading.Tasks;
-using Altinn.Studio.Designer.Models;
-using Designer.Tests.Utils;
-using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
-using SharedResources.Tests;
using Xunit;
namespace Designer.Tests.Controllers.PreviewController
@@ -17,30 +13,12 @@ public LayoutSetsTests(WebApplicationFactory factory) : base(factory)
{
}
- [Fact]
- public async Task Get_LayoutSets_ShouldReturnLayoutSetsWithoutAnyUndefinedDataTypes()
- {
- string actualLayoutSetsString = TestDataHelper.GetFileFromRepo(Org, AppV4, Developer, "App/ui/layout-sets.json");
- LayoutSets actualLayoutSets = JsonSerializer.Deserialize(actualLayoutSetsString);
-
- string dataPathWithData = $"{Org}/{AppV4}/api/layoutsets";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- LayoutSets responseLayoutSets = JsonSerializer.Deserialize(responseBody);
-
- actualLayoutSets.Sets.Exists(set => set.DataType is null).Should().BeTrue();
- responseLayoutSets.Sets.Exists(set => set.DataType is null).Should().BeFalse();
- }
-
[Fact]
public async Task Get_LayoutSets_NotFound()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/layoutsets";
+ string dataPathWithData = $"{Org}/{AppV4}/api/layoutsets";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3Path}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSettingsTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSettingsTests.cs
index 795418d82e1..16f328fbc44 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSettingsTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/LayoutSettingsTests.cs
@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Designer.Tests.Utils;
@@ -9,12 +10,10 @@
namespace Designer.Tests.Controllers.PreviewController
{
- public class LayoutSettingsTests : PreviewControllerTestsBase, IClassFixture>
+ public class LayoutSettingsTests(
+ WebApplicationFactory factory
+ ) : PreviewControllerTestsBase(factory), IClassFixture>
{
- public LayoutSettingsTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
[Fact]
public async Task Get_LayoutSettings_Ok()
{
@@ -22,6 +21,7 @@ public async Task Get_LayoutSettings_Ok()
string dataPathWithData = $"{Org}/{AppV3}/api/layoutsettings";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/PostAttachmentTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/PostAttachmentTests.cs
index c01b4ddbd3f..09f39c27ef1 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/PostAttachmentTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/PostAttachmentTests.cs
@@ -2,6 +2,7 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
@@ -18,9 +19,9 @@ public PostAttachmentTests(WebApplicationFactory factory) : base(factor
[Fact]
public async Task Post_Attachment_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/data?dataType=FileUploadId";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{instance.Id}/data?dataType=FileUploadId";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
@@ -29,9 +30,9 @@ public async Task Post_Attachment_Ok()
[Fact]
public async Task Post_AttachmentForV4App_Ok()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/data?dataType=FileUploadId";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data?dataType=FileUploadId";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(StatusCodes.Status201Created, (int)response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/PreviewControllerTestsBase.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/PreviewControllerTestsBase.cs
index b0ca17543ea..0f24aa57773 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/PreviewControllerTestsBase.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/PreviewControllerTestsBase.cs
@@ -1,28 +1,31 @@
using System.Linq;
-using System.Text.Encodings.Web;
+using System.Net;
+using System.Net.Http;
using System.Text.Json;
-using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Designer.Tests.Controllers.ApiTests;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
+using Xunit;
namespace Designer.Tests.Controllers.PreviewController
{
- public class PreviewControllerTestsBase : DesignerEndpointsTestsBase
+ public class PreviewControllerTestsBase(WebApplicationFactory factory) : DesignerEndpointsTestsBase(factory)
where TTestClass : class
{
protected const string Org = "ttd";
protected const string AppV3 = "app-without-layoutsets";
+ protected const string AppV3Path = "app-without-layoutsets/V3";
protected const string AppV4 = "app-with-layoutsets";
protected const string PreviewApp = "preview-app";
protected const string Developer = "testUser";
protected const string LayoutSetName = "layoutSet1";
protected const string LayoutSetName2 = "layoutSet2";
- protected const string CustomReceiptLayoutSetName = "receipt";
- protected const string CustomReceiptDataType = "datamodel";
protected const string PartyId = "51001";
- protected const string InstanceGuId = "f1e23d45-6789-1bcd-8c34-56789abcdef0";
+ protected const string V3InstanceId = "f1e23d45-6789-1bcd-8c34-56789abcdef0";
+ protected const string TaskId = "Task_1";
protected const string AttachmentGuId = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
protected const string MockedReferrerUrl = "https://studio-mock-url.no";
@@ -39,10 +42,29 @@ protected override void ConfigureTestServices(IServiceCollection services)
services.AddDistributedMemoryCache();
}
- public PreviewControllerTestsBase(WebApplicationFactory factory) : base(factory)
+ protected async Task createInstance()
{
+ string dataPath = $"{Org}/{AppV4}/instances?instanceOwnerPartyId={PartyId}&taskId={TaskId}";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPath);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ string responseBody = await response.Content.ReadAsStringAsync();
+ Instance dataItem = JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
+ Assert.NotNull(dataItem);
+ return dataItem;
}
+ protected async Task createDataElement(Instance instance, string dataType)
+ {
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/data?dataType={dataType}";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.Created, response.StatusCode);
+ string responseBody = await response.Content.ReadAsStringAsync();
+ DataElement dataElement = JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
+ Assert.NotNull(dataElement);
+ return dataElement;
+ }
}
}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessNextTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessNextTests.cs
index 9921c5ad3e4..43c07946b6f 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessNextTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessNextTests.cs
@@ -10,19 +10,15 @@
namespace Designer.Tests.Controllers.PreviewController
{
- public class ProcessNextTests : PreviewControllerTestsBase, IClassFixture>
+ public class ProcessNextTests(WebApplicationFactory factory)
+ : PreviewControllerTestsBase(factory), IClassFixture>
{
-
- public ProcessNextTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
[Fact]
public async Task Get_ProcessNext_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/process/next";
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{V3InstanceId}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3Path}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@@ -31,15 +27,15 @@ public async Task Get_ProcessNext_Ok()
JsonDocument responseDocument = JsonDocument.Parse(responseBody);
ProcessState processState = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
Assert.Equal("data", processState.CurrentTask.AltinnTaskType);
- Assert.Equal("Task_1", processState.CurrentTask.ElementId);
+ Assert.Equal(TaskId, processState.CurrentTask.ElementId);
}
[Fact]
public async Task Get_ProcessNextForV4App_Ok()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/process/next";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@@ -48,7 +44,7 @@ public async Task Get_ProcessNextForV4App_Ok()
JsonDocument responseDocument = JsonDocument.Parse(responseBody);
ProcessState processState = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
Assert.Equal("data", processState.CurrentTask.AltinnTaskType);
- Assert.Equal("Task_1", processState.CurrentTask.ElementId);
+ Assert.Equal(TaskId, processState.CurrentTask.ElementId);
}
}
}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessTests.cs
deleted file mode 100644
index d3de435bb51..00000000000
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/ProcessTests.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Http;
-using System.Text.Json;
-using System.Threading.Tasks;
-using Altinn.App.Core.Internal.Process.Elements;
-using Altinn.Platform.Storage.Interface.Models;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace Designer.Tests.Controllers.PreviewController
-{
- public class ProcessTests : PreviewControllerTestsBase, IClassFixture>
- {
-
- public ProcessTests(WebApplicationFactory factory) : base(factory)
- {
- }
-
- [Fact]
- public async Task Get_Process_Ok()
- {
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/process";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- ProcessState processState = JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
- Assert.Equal("data", processState.CurrentTask.AltinnTaskType);
- Assert.Equal("Task_1", processState.CurrentTask.ElementId);
- }
-
- [Fact]
- public async Task Get_ProcessForV4App_Ok()
- {
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/process";
- using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
-
- using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- AppProcessState processState =
- JsonSerializer.Deserialize(responseBody, JsonSerializerOptions);
- var expectedProcessTasks = new List
- {
- new AppProcessTaskTypeInfo
- {
- ElementId = "Task_1",
- AltinnTaskType = "data"
- },
- new AppProcessTaskTypeInfo
- {
- ElementId = "Task_2",
- AltinnTaskType = "data"
- },
- new AppProcessTaskTypeInfo
- {
- ElementId = "Task_3",
- AltinnTaskType = "data"
- }
- };
- Assert.Equal("data", processState.CurrentTask.AltinnTaskType);
- Assert.Equal("Task_1", processState.CurrentTask.ElementId);
- expectedProcessTasks.Should().BeEquivalentTo(processState.ProcessTasks);
- }
- }
-}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateFormDataTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateFormDataTests.cs
index 1402307492f..75d062056a5 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateFormDataTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateFormDataTests.cs
@@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
+using Altinn.Platform.Storage.Interface.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
@@ -17,9 +18,9 @@ public UpdateFormDataTests(WebApplicationFactory factory) : base(factor
[Fact]
public async Task Put_UpdateFormData_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{instance.Id}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(StatusCodes.Status200OK, (int)response.StatusCode);
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateProcessNextTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateProcessNextTests.cs
index 430382d3cb6..698dfacb4e0 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateProcessNextTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/UpdateProcessNextTests.cs
@@ -20,23 +20,21 @@ public UpdateProcessNextTests(WebApplicationFactory factory) : base(fac
[Fact]
public async Task Put_ProcessNext_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/instances/{PartyId}/{InstanceGuId}/process/next";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV3Path}/instances/{PartyId}/{instance.Id}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3}&selectedLayoutSet=");
+ httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV3Path}&selectedLayoutSet=");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
- string responseBody = await response.Content.ReadAsStringAsync();
- Assert.Equal(@"{""ended"": ""ended""}", responseBody);
}
[Fact]
public async Task Put_ProcessNextForV4AppForNonExistingTask_Ok()
{
- string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{InstanceGuId}/process/next";
+ Instance instance = await createInstance();
+ string dataPathWithData = $"{Org}/{AppV4}/instances/{PartyId}/{instance.Id}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
- httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={AppV4}&selectedLayoutSet={LayoutSetName}");
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@@ -45,7 +43,7 @@ public async Task Put_ProcessNextForV4AppForNonExistingTask_Ok()
JsonDocument responseDocument = JsonDocument.Parse(responseBody);
ProcessState processState = JsonConvert.DeserializeObject(responseDocument.RootElement.ToString());
Assert.Equal("data", processState.CurrentTask.AltinnTaskType);
- Assert.Equal("Task_1", processState.CurrentTask.ElementId);
+ Assert.Equal(TaskId, processState.CurrentTask.ElementId);
}
}
}
diff --git a/backend/tests/Designer.Tests/Controllers/PreviewController/ValidateInstantiationTests.cs b/backend/tests/Designer.Tests/Controllers/PreviewController/ValidateInstantiationTests.cs
index 604395526d0..90ceb284e79 100644
--- a/backend/tests/Designer.Tests/Controllers/PreviewController/ValidateInstantiationTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/PreviewController/ValidateInstantiationTests.cs
@@ -18,7 +18,7 @@ public ValidateInstantiationTests(WebApplicationFactory factory) : base
[Fact]
public async Task Post_ValidateInstantiation_Ok()
{
- string dataPathWithData = $"{Org}/{AppV3}/api/v1/parties/validateInstantiation";
+ string dataPathWithData = $"{Org}/{AppV4}/api/v1/parties/validateInstantiation";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
diff --git a/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AccessListTests.cs b/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AccessListTests.cs
index 1ba2641b5b9..104b5e5e408 100644
--- a/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AccessListTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AccessListTests.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using System.Net;
+using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
diff --git a/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AddResourceTests.cs b/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AddResourceTests.cs
index 184b9077f23..82d2e4a4884 100644
--- a/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AddResourceTests.cs
+++ b/backend/tests/Designer.Tests/Controllers/ResourceAdminController/AddResourceTests.cs
@@ -34,6 +34,7 @@ public async Task AddServiceResource_StatusCreated()
RightDescription = new Dictionary { { "en", "Access Management" }, { "no", "Tilgangsstyring" } },
Homepage = "test.no",
Status = "Active",
+ ContactPoints = null,
IsPartOf = "Altinn",
ThematicArea = "",
ResourceReferences = GetTestResourceReferences(),
diff --git a/backend/tests/Designer.Tests/Helpers/WebScrapingUtils.cs b/backend/tests/Designer.Tests/Helpers/WebScrapingUtils.cs
index 681b22fce6f..a54b54cd4a6 100644
--- a/backend/tests/Designer.Tests/Helpers/WebScrapingUtils.cs
+++ b/backend/tests/Designer.Tests/Helpers/WebScrapingUtils.cs
@@ -10,7 +10,7 @@ public static class WebScrapingUtils
/// The HTML content from which the substring will be extracted.
/// The text that appears immediately before the desired substring. If there are multiple matches, only first will be considered.
/// The text that appears immediately after the desired substring.
- /// The extracted substring between and if they are found in the HTML content and are in the correct order.
+ /// The extracted substring between "beforeText" and "afterText" if they are found in the HTML content and are in the correct order.
/// Returns null if the conditions are not met.
///
public static string ExtractTextBetweenMarkers(string htmlContent, string beforeText, string afterText)
diff --git a/backend/tests/Designer.Tests/Services/AppDevelopmentServiceTest.cs b/backend/tests/Designer.Tests/Services/AppDevelopmentServiceTest.cs
index 03175e8fc92..629ec88fd7d 100644
--- a/backend/tests/Designer.Tests/Services/AppDevelopmentServiceTest.cs
+++ b/backend/tests/Designer.Tests/Services/AppDevelopmentServiceTest.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
+using Altinn.Common.EFormidlingClient.Models.SBD;
using Altinn.Studio.Designer.Exceptions.AppDevelopment;
using Altinn.Studio.Designer.Factories;
using Altinn.Studio.Designer.Models;
@@ -203,7 +204,7 @@ public async Task AddLayoutSet_WhenAppHasNoLayoutSets_ShouldThrowFileNotFoundExc
CreatedTestRepoPath = await TestDataHelper.CopyRepositoryForTest(_org, repository, _developer, targetRepository);
// Act
- Func act = async () => await _appDevelopmentService.AddLayoutSet(AltinnRepoEditingContext.FromOrgRepoDeveloper(_org, targetRepository, _developer), new LayoutSetConfig());
+ Func act = async () => await _appDevelopmentService.AddLayoutSet(AltinnRepoEditingContext.FromOrgRepoDeveloper(_org, targetRepository, _developer), new() { Id = "layoutSet1" });
// Assert
await act.Should().ThrowAsync();
diff --git a/backend/tests/Designer.Tests/Services/OptionsServiceTests.cs b/backend/tests/Designer.Tests/Services/OptionsServiceTests.cs
index 3d787539035..6404416c048 100644
--- a/backend/tests/Designer.Tests/Services/OptionsServiceTests.cs
+++ b/backend/tests/Designer.Tests/Services/OptionsServiceTests.cs
@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Altinn.Studio.Designer.Factories;
using Altinn.Studio.Designer.Models;
+using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.Services.Implementation;
using Designer.Tests.Utils;
using LibGit2Sharp;
@@ -238,18 +239,69 @@ public async Task OptionListsExists_ShouldReturnFalse_WhenOptionsListDoesNotExis
// Arrange
const string repo = "empty-app";
const string optionListId = "test-options";
- string targetRepository = TestDataHelper.GenerateTestRepoName();
- await TestDataHelper.CopyRepositoryForTest(Org, repo, Developer, targetRepository);
var optionsService = GetOptionsServiceForTest();
// Act
- bool optionListExists = await optionsService.OptionsListExists(Org, targetRepository, Developer, optionListId);
+ bool optionListExists = await optionsService.OptionsListExists(Org, repo, Developer, optionListId);
// Assert
Assert.False(optionListExists);
}
+ [Fact]
+ public async Task GetAllOptionListReferences_ShouldReturnAllReferences_WhenOptionsListExists()
+ {
+ // Arrange
+ const string repo = "app-with-options";
+ var optionsService = GetOptionsServiceForTest();
+
+ // Act
+ List optionListsReferences = await optionsService.GetAllOptionListReferences(AltinnRepoEditingContext.FromOrgRepoDeveloper(Org, repo, Developer));
+
+ List expectedResponseList = new()
+ {
+ new RefToOptionListSpecifier
+ {
+ OptionListId = "test-options", OptionListIdSources =
+ [
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-same-options-id-in-same-set-and-another-layout"],
+ LayoutName = "layoutWithOneOptionListIdRef.json",
+ LayoutSetId = "layoutSet1"
+ },
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-test-options-id", "component-using-test-options-id-again"],
+ LayoutName = "layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json",
+ LayoutSetId = "layoutSet1"
+ },
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-same-options-id-in-another-set"],
+ LayoutName = "layoutWithTwoOptionListIdRefs.json",
+ LayoutSetId = "layoutSet2"
+ }
+ ]
+ },
+ new()
+ {
+ OptionListId = "other-options", OptionListIdSources =
+ [
+ new OptionListIdSource
+ {
+ ComponentIds = ["component-using-other-options-id"],
+ LayoutName = "layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json",
+ LayoutSetId = "layoutSet1"
+ }
+ ]
+ }
+ };
+ // Assert
+ Assert.Equivalent(optionListsReferences, expectedResponseList);
+ }
+
private static OptionsService GetOptionsServiceForTest()
{
AltinnGitRepositoryFactory altinnGitRepositoryFactory = new(TestDataHelper.GetTestDataRepositoriesRootDirectory());
diff --git a/backend/tests/Designer.Tests/Services/SchemaModelServiceTests.cs b/backend/tests/Designer.Tests/Services/SchemaModelServiceTests.cs
index a4febf21116..344f341d896 100644
--- a/backend/tests/Designer.Tests/Services/SchemaModelServiceTests.cs
+++ b/backend/tests/Designer.Tests/Services/SchemaModelServiceTests.cs
@@ -15,6 +15,7 @@
using Altinn.Studio.Designer.Services.Interfaces;
using Designer.Tests.Utils;
using FluentAssertions;
+using Moq;
using SharedResources.Tests;
using Xunit;
@@ -22,6 +23,17 @@ namespace Designer.Tests.Services
{
public class SchemaModelServiceTests
{
+ private readonly Mock _applicationMetadataService;
+ private readonly AltinnGitRepositoryFactory _altinnGitRepositoryFactory;
+ private readonly ISchemaModelService _schemaModelService;
+
+ public SchemaModelServiceTests()
+ {
+ _applicationMetadataService = new Mock();
+ _altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
+ _schemaModelService = new SchemaModelService(_altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter, _applicationMetadataService.Object);
+ }
+
[Fact]
public async Task DeleteSchema_AppRepo_ShouldDelete()
{
@@ -35,22 +47,19 @@ public async Task DeleteSchema_AppRepo_ShouldDelete()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
-
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
- var schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ var schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(7);
- var altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
+ var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
var applicationMetadata = await altinnAppGitRepository.GetApplicationMetadata();
applicationMetadata.DataTypes.Should().HaveCount(2);
// Act
var schemaToDelete = schemaFiles.First(s => s.FileName == "Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.schema.json");
- await schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
+ await _schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
// Assert
- schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(6);
applicationMetadata = await altinnAppGitRepository.GetApplicationMetadata();
applicationMetadata.DataTypes.Should().HaveCount(1);
@@ -75,22 +84,20 @@ public async Task DeleteSchema_AppRepoWithLayoutSets_ShouldDelete()
try
{
string dataModelName = "datamodel";
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
- var schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ var schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(1);
- var altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
+ var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
var applicationMetadataBefore = await altinnAppGitRepository.GetApplicationMetadata();
var layoutSetsBefore = await altinnAppGitRepository.GetLayoutSetsFile();
// Act
var schemaToDelete = schemaFiles.First(s => s.FileName == $"{dataModelName}.schema.json");
- await schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
+ await _schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
// Assert
- schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(0);
var applicationMetadataAfter = await altinnAppGitRepository.GetApplicationMetadata();
applicationMetadataAfter.DataTypes.Should().HaveCount(applicationMetadataBefore.DataTypes.Count - 1);
@@ -117,18 +124,16 @@ public async Task DeleteSchema_ModelsRepo_ShouldDelete()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
- var schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ var schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(6);
// Act
var schemaToDelete = schemaFiles.First(s => s.FileName == "Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.schema.json");
- await schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
+ await _schemaModelService.DeleteSchema(editingContext, schemaToDelete.RepositoryRelativeUrl);
// Assert
- schemaFiles = schemaModelService.GetSchemaFiles(editingContext);
+ schemaFiles = _schemaModelService.GetSchemaFiles(editingContext);
schemaFiles.Should().HaveCount(5);
}
finally
@@ -150,15 +155,13 @@ public async Task UpdateSchema_AppRepo_ShouldUpdate()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
// Act
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var expectedSchemaUpdates = @"{""properties"":{""rootType1"":{""$ref"":""#/definitions/rootType""}},""definitions"":{""rootType"":{""properties"":{""keyword"":{""type"":""string""}}}}}";
- await schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", expectedSchemaUpdates);
+ await _schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", expectedSchemaUpdates);
// Assert
- var altinnGitRepository = altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
+ var altinnGitRepository = _altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
var updatedSchema = await altinnGitRepository.ReadTextByRelativePathAsync("App/models/HvemErHvem_SERES.schema.json");
string serializedExpectedSchemaUpdates = FormatJsonString(updatedSchema);
@@ -199,13 +202,11 @@ public async Task UpdateSchema_ModelMetadataExistForModelInRepo_ShouldDeleteMode
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var updatedSchema = @"{""properties"":{""rootType1"":{""$ref"":""#/definitions/rootType""}},""definitions"":{""rootType"":{""properties"":{""keyword"":{""type"":""string""}}}}}";
- var altinnGitRepository = altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
+ var altinnGitRepository = _altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
Assert.True(altinnGitRepository.FileExistsByRelativePath("App/models/Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.metadata.json"));
- await schemaModelService.UpdateSchema(editingContext, "App/models/Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.schema.json", updatedSchema);
+ await _schemaModelService.UpdateSchema(editingContext, "App/models/Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.schema.json", updatedSchema);
Assert.False(altinnGitRepository.FileExistsByRelativePath("App/models/Kursdomene_HvemErHvem_M_2021-04-08_5742_34627_SERES.metadata.json"));
}
finally
@@ -227,13 +228,11 @@ public async Task UpdateSchema_NoModelMetadataForModelInRepo_ShouldOnlyUpdate()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var expectedUpdatedSchema = @"{""properties"":{""rootType1"":{""$ref"":""#/definitions/rootType""}},""definitions"":{""rootType"":{""properties"":{""keyword"":{""type"":""string""}}}}}";
- var altinnGitRepository = altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
+ var altinnGitRepository = _altinnGitRepositoryFactory.GetAltinnGitRepository(org, targetRepository, developer);
Assert.False(altinnGitRepository.FileExistsByRelativePath("App/models/HvemErHvem_SERES.metadata.json"));
- await schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", expectedUpdatedSchema);
+ await _schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", expectedUpdatedSchema);
Assert.False(altinnGitRepository.FileExistsByRelativePath("App/models/HvemErHvem_SERES.metadata.json"));
var updatedSchema = await altinnGitRepository.ReadTextByRelativePathAsync("App/models/HvemErHvem_SERES.schema.json");
string serializedExpectedSchemaUpdates = FormatJsonString(updatedSchema);
@@ -257,37 +256,18 @@ public async Task UpdateSchema_InvalidJsonSchema_ShouldThrowException()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
-
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory,
- TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings,
- TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter,
- TestDataHelper.ModelMetadataToCsharpConverter);
var invalidSchema =
@"{""properties"":{""root"":{""$ref"":""#/definitions/rootType""}},""definitions"":{""rootType"":{""properties"":{""keyword"":{""type"":""string""}}}}}";
var exception = await Assert.ThrowsAsync(async () =>
{
- await schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", invalidSchema);
+ await _schemaModelService.UpdateSchema(editingContext, "App/models/HvemErHvem_SERES.schema.json", invalidSchema);
});
Assert.NotNull(exception.CustomErrorMessages);
exception.CustomErrorMessages.Should().ContainSingle(c => c.Contains("root': member names cannot be the same as their enclosing type"));
}
- [Theory]
- [InlineData("ttd", "apprepo", "test", "", "http://studio.localhost/repos")]
- [InlineData("ttd", "apprepo", "test", "/path/to/folder/", "http://studio.localhost/repos")]
- public void GetSchemaUri_ValidNameProvided_ShouldReturnUri(string org, string repository, string schemaName, string relativePath, string repositoryBaseUrl)
- {
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- var schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
-
- var schemaUri = schemaModelService.GetSchemaUri(org, repository, schemaName, relativePath);
-
- schemaUri.AbsoluteUri.Should().Be($"{repositoryBaseUrl}/{org}/{repository}{(string.IsNullOrEmpty(relativePath) ? "/" : relativePath)}{schemaName}.schema.json");
- }
-
[Fact]
public async Task UploadSchemaFromXsd_InvalidXsd_ThrowsException()
{
@@ -301,13 +281,11 @@ public async Task UploadSchemaFromXsd_InvalidXsd_ThrowsException()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var xsdStream = SharedResourcesHelper.LoadTestData("Model/XmlSchema/General/SimpleInvalidNonSeresSchema.xsd");
var schemaName = "SimpleInvalidNonSeresSchema";
var fileName = $"{schemaName}.xsd";
- Func action = () => schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
+ Func action = () => _schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
// Act/assert
await action.Should().ThrowAsync();
@@ -333,8 +311,6 @@ public async Task UploadSchemaFromXsd_ValidNonSeresXsd_ModelsCreated()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var xsdStream = SharedResourcesHelper.LoadTestData("Model/XmlSchema/General/SimpleValidNonSeresSchema.xsd");
var schemaName = "SimpleValidNonSeresSchema";
var fileName = $"{schemaName}.xsd";
@@ -342,10 +318,10 @@ public async Task UploadSchemaFromXsd_ValidNonSeresXsd_ModelsCreated()
var relativeFilePath = $"{relativeDirectory}/{fileName}";
// Act
- await schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
+ await _schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
// Assert
- var altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
+ var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.metadata.json").Should().BeFalse();
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.schema.json").Should().BeTrue();
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.cs").Should().BeTrue();
@@ -371,8 +347,6 @@ public async Task UploadSchemaFromXsd_OED_ModelsCreated()
await TestDataHelper.CopyRepositoryForTest(org, sourceRepository, developer, targetRepository);
try
{
- var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
- ISchemaModelService schemaModelService = new SchemaModelService(altinnGitRepositoryFactory, TestDataHelper.LogFactory, TestDataHelper.ServiceRepositorySettings, TestDataHelper.XmlSchemaToJsonSchemaConverter, TestDataHelper.JsonSchemaToXmlSchemaConverter, TestDataHelper.ModelMetadataToCsharpConverter);
var xsdStream = SharedResourcesHelper.LoadTestData("Model/XmlSchema/Gitea/OED.xsd");
var schemaName = "OED_M";
var fileName = $"{schemaName}.xsd";
@@ -380,10 +354,10 @@ public async Task UploadSchemaFromXsd_OED_ModelsCreated()
var relativeFilePath = $"{relativeDirectory}/{fileName}";
// Act
- await schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
+ await _schemaModelService.BuildSchemaFromXsd(editingContext, fileName, xsdStream);
// Assert
- var altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
+ var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, targetRepository, developer);
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.metadata.json").Should().BeFalse();
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.schema.json").Should().BeTrue();
altinnAppGitRepository.FileExistsByRelativePath($"{relativeDirectory}/{schemaName}.xsd").Should().BeTrue();
diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json
new file mode 100644
index 00000000000..afc15b4d56a
--- /dev/null
+++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithFourCheckboxComponentsAndThreeOptionListIdRefs.json
@@ -0,0 +1,34 @@
+{
+ "schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json",
+ "data": {
+ "layout": [
+ {
+ "id": "component-using-manual-options",
+ "type": "Checkboxes",
+ "options": [
+ {
+ "value": "1",
+ "label": "id-used-by-options",
+ "helpText": "help-text-used-by-options",
+ "description": "description-used-by-options"
+ }
+ ]
+ },
+ {
+ "id": "component-using-test-options-id",
+ "type": "Checkboxes",
+ "optionsId": "test-options"
+ },
+ {
+ "id": "component-using-test-options-id-again",
+ "type": "Checkboxes",
+ "optionsId": "test-options"
+ },
+ {
+ "id": "component-using-other-options-id",
+ "type": "Checkboxes",
+ "optionsId": "other-options"
+ }
+ ]
+ }
+}
diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithOneOptionListIdRef.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithOneOptionListIdRef.json
new file mode 100644
index 00000000000..65b1de4f879
--- /dev/null
+++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet1/layouts/layoutWithOneOptionListIdRef.json
@@ -0,0 +1,12 @@
+{
+ "schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json",
+ "data": {
+ "layout": [
+ {
+ "id": "component-using-same-options-id-in-same-set-and-another-layout",
+ "type": "Checkboxes",
+ "optionsId": "test-options"
+ }
+ ]
+ }
+}
diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet2/layouts/layoutWithTwoOptionListIdRefs.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet2/layouts/layoutWithTwoOptionListIdRefs.json
new file mode 100644
index 00000000000..3a81c463d6a
--- /dev/null
+++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-options/App/ui/layoutSet2/layouts/layoutWithTwoOptionListIdRefs.json
@@ -0,0 +1,17 @@
+{
+ "schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json",
+ "data": {
+ "layout": [
+ {
+ "id": "component-using-same-options-id-in-another-set",
+ "type": "Checkboxes",
+ "optionsId": "test-options"
+ },
+ {
+ "id": "component-using-a-custom-options-id",
+ "type": "Checkboxes",
+ "optionsId": "custom-options-id"
+ }
+ ]
+ }
+}
diff --git a/development/azure-devops-mock/package.json b/development/azure-devops-mock/package.json
index 3594cd34bc4..56c1da5a7d8 100644
--- a/development/azure-devops-mock/package.json
+++ b/development/azure-devops-mock/package.json
@@ -8,7 +8,7 @@
"cors": "2.8.5",
"express": "4.21.2",
"morgan": "1.10.0",
- "nodemon": "3.1.7",
+ "nodemon": "3.1.9",
"p-queue": "8.0.1"
},
"license": "MIT",
diff --git a/eidlogger/pom.xml b/eidlogger/pom.xml
index fee662753ad..dcc55126bbc 100644
--- a/eidlogger/pom.xml
+++ b/eidlogger/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.4.0
+ 3.4.1
no.altinn
@@ -17,7 +17,7 @@
21
2.7.0
1.2.2
- 5.18.0
+ 5.19.0
diff --git a/frontend/app-preview/src/components/PreviewControlHeader/PreviewControlHeader.test.tsx b/frontend/app-preview/src/components/PreviewControlHeader/PreviewControlHeader.test.tsx
index 1ffd699e473..66031450194 100644
--- a/frontend/app-preview/src/components/PreviewControlHeader/PreviewControlHeader.test.tsx
+++ b/frontend/app-preview/src/components/PreviewControlHeader/PreviewControlHeader.test.tsx
@@ -10,7 +10,6 @@ import { type ServicesContextProps } from 'app-shared/contexts/ServicesContext';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { type QueryClient } from '@tanstack/react-query';
import { QueryKey } from 'app-shared/types/QueryKey';
-import { useInstanceIdQuery } from 'app-shared/hooks/queries';
// Move
jest.mock('app-shared/hooks/queries');
@@ -122,7 +121,6 @@ describe('PreviewControlHeader', () => {
});
it('should not render the layout sets dropdown if layoutSets is not available', () => {
- (useInstanceIdQuery as jest.Mock).mockReturnValue(mockLayoutId);
renderPreviewControlHeader();
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
diff --git a/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.test.tsx b/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.test.tsx
index 8e6421493ba..adc9f0d0dad 100644
--- a/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.test.tsx
+++ b/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.test.tsx
@@ -5,7 +5,7 @@ import { app, org } from '@studio/testing/testids';
import { RoutePaths } from 'app-development/enums/RoutePaths';
const mockLayoutId: string = 'layout1';
-const mockUiEditorPath: string = `/editor/${org}/${app}/${RoutePaths.UIEditor}?layout=${mockLayoutId}`;
+const mockUiEditorPath: string = `/editor/${org}/${app}/${RoutePaths.UIEditor}`;
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
diff --git a/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.tsx b/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.tsx
index fc666e20119..126eb470cbe 100644
--- a/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.tsx
+++ b/frontend/app-preview/src/hooks/useBackToEditingHref/useBackToEditingHref.tsx
@@ -1,14 +1,10 @@
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { PackagesRouter } from 'app-shared/navigation/PackagesRouter';
-import { typedLocalStorage } from '@studio/pure-functions';
-import { useInstanceIdQuery } from 'app-shared/hooks/queries';
export const useBackToEditingHref = () => {
const { org, app } = useStudioEnvironmentParams();
- const { data: instanceId } = useInstanceIdQuery(org, app);
const packagesRouter = new PackagesRouter({ org, app });
- const queryParams: string = `?layout=${typedLocalStorage.getItem(instanceId)}`;
- return `${packagesRouter.getPackageNavigationUrl('editorUiEditor')}${queryParams}`;
+ return `${packagesRouter.getPackageNavigationUrl('editorUiEditor')}`;
};
diff --git a/frontend/app-preview/src/views/LandingPage.test.tsx b/frontend/app-preview/src/views/LandingPage.test.tsx
index dca0563d168..a883fec8749 100644
--- a/frontend/app-preview/src/views/LandingPage.test.tsx
+++ b/frontend/app-preview/src/views/LandingPage.test.tsx
@@ -19,6 +19,10 @@ jest.mock('react-router-dom', () => ({
}),
}));
+jest.mock('app-shared/api/mutations', () => ({
+ createPreviewInstance: jest.fn().mockReturnValue(Promise.resolve({ id: 1 })),
+}));
+
const mockGetItem = jest.fn();
Object.defineProperty(window, 'localStorage', {
diff --git a/frontend/app-preview/src/views/LandingPage.tsx b/frontend/app-preview/src/views/LandingPage.tsx
index a09a2930bff..758b4c6e892 100644
--- a/frontend/app-preview/src/views/LandingPage.tsx
+++ b/frontend/app-preview/src/views/LandingPage.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import classes from './LandingPage.module.css';
import { useTranslation } from 'react-i18next';
import { usePreviewConnection } from 'app-shared/providers/PreviewConnectionContext';
@@ -16,6 +16,7 @@ import { useSelectedFormLayoutName } from 'app-shared/hooks/useSelectedFormLayou
import { useSelectedFormLayoutSetName } from 'app-shared/hooks/useSelectedFormLayoutSetName';
import { useSelectedTaskId } from 'app-shared/hooks/useSelectedTaskId';
import { useLayoutSetsQuery } from 'app-shared/hooks/queries/useLayoutSetsQuery';
+import { useCreatePreviewInstanceMutation } from 'app-shared/hooks/mutations/useCreatePreviewInstanceMutation';
export type PreviewAsViewSize = 'desktop' | 'mobile';
@@ -26,17 +27,25 @@ export const LandingPage = () => {
const previewConnection = usePreviewConnection();
const { data: user, isPending: isPendingUser } = useUserQuery();
const { data: repository } = useRepoMetadataQuery(org, app);
-
const { data: layoutSets, isPending: pendingLayoutsets } = useLayoutSetsQuery(org, app);
const { selectedFormLayoutSetName, setSelectedFormLayoutSetName } =
useSelectedFormLayoutSetName(layoutSets);
-
const { selectedFormLayoutName } = useSelectedFormLayoutName(selectedFormLayoutSetName);
const [previewViewSize, setPreviewViewSize] = useLocalStorage(
'viewSize',
'desktop',
);
const taskId = useSelectedTaskId(selectedFormLayoutSetName);
+ const {
+ mutate: createInstance,
+ data: instance,
+ isPending: instanceIsPending,
+ } = useCreatePreviewInstanceMutation(org, app);
+
+ useEffect(() => {
+ if (user && taskId) createInstance({ partyId: user?.id, taskId: taskId });
+ }, [createInstance, user, taskId]);
+
const isIFrame = (input: HTMLElement | null): input is HTMLIFrameElement =>
input !== null && input.tagName === 'IFRAME';
@@ -59,9 +68,17 @@ export const LandingPage = () => {
});
}
- if (isPendingUser || pendingLayoutsets)
+ if (isPendingUser || pendingLayoutsets || instanceIsPending)
return ;
+ const previewUrl = previewPage(
+ org,
+ app,
+ getSelectedFormLayoutSetName(selectedFormLayoutSetName),
+ taskId,
+ selectedFormLayoutName,
+ instance?.id,
+ );
return (
<>
@@ -87,13 +104,7 @@ export const LandingPage = () => {
diff --git a/frontend/libs/studio-components/package.json b/frontend/libs/studio-components/package.json
index 56a3dd4a574..1debe85a4ef 100644
--- a/frontend/libs/studio-components/package.json
+++ b/frontend/libs/studio-components/package.json
@@ -20,7 +20,7 @@
"uuid": "10.0.0"
},
"devDependencies": {
- "@chromatic-com/storybook": "3.2.2",
+ "@chromatic-com/storybook": "3.2.3",
"@storybook/addon-essentials": "8.4.7",
"@storybook/addon-interactions": "8.4.7",
"@storybook/addon-links": "8.4.7",
diff --git a/frontend/libs/studio-components/src/components/StudioGridSelector/StudioGridSelector.module.css b/frontend/libs/studio-components/src/components/StudioGridSelector/StudioGridSelector.module.css
index 460f8f5bcde..72d49e92e27 100644
--- a/frontend/libs/studio-components/src/components/StudioGridSelector/StudioGridSelector.module.css
+++ b/frontend/libs/studio-components/src/components/StudioGridSelector/StudioGridSelector.module.css
@@ -38,19 +38,19 @@
border-radius: var(--border-radius);
}
-.range::-moz-range-track {
- aspect-ratio: 12;
- background: var(--background);
- border-radius: var(--border-radius);
-}
-
.range::-webkit-slider-thumb {
-webkit-appearance: none;
- appearance: none;
width: var(--thumb-width);
}
+.range::-moz-range-track {
+ height: 100%;
+ background: var(--background);
+ border-radius: var(--border-radius);
+}
+
.range::-moz-range-thumb {
+ visibility: hidden;
width: var(--thumb-width);
}
diff --git a/frontend/packages/shared/package.json b/frontend/packages/shared/package.json
index 52e462ff57f..47215eb50e5 100644
--- a/frontend/packages/shared/package.json
+++ b/frontend/packages/shared/package.json
@@ -10,7 +10,7 @@
"react-router-dom": "6.28.0"
},
"devDependencies": {
- "@types/react": "18.3.16",
+ "@types/react": "18.3.18",
"jest": "29.7.0",
"typescript": "5.7.2"
},
diff --git a/frontend/packages/shared/src/api/mutations.ts b/frontend/packages/shared/src/api/mutations.ts
index b6f5205313d..ae1f535b21e 100644
--- a/frontend/packages/shared/src/api/mutations.ts
+++ b/frontend/packages/shared/src/api/mutations.ts
@@ -45,6 +45,7 @@ import {
optionListIdUpdatePath,
processEditorPath,
selectedMaskinportenScopesPath,
+ createInstancePath,
} from 'app-shared/api/paths';
import type { AddLanguagePayload } from 'app-shared/types/api/AddLanguagePayload';
import type { AddRepoParams } from 'app-shared/types/api';
@@ -140,6 +141,9 @@ export const updatePolicy = (org: string, repo: string, id: string, payload: Pol
export const updateResource = (org: string, repo: string, payload: Resource) => put(resourceEditPath(org, repo), payload);
export const migrateDelegations = (org: string, env: string, payload: MigrateDelegationsRequest) => post(altinn2DelegationsMigrationPath(org, env), payload);
+// Preview
+export const createPreviewInstance = (org: string, app: string, partyId: number, taskId: string) => post(createInstancePath(org, app, partyId, taskId), {}, { headers });
+
// ProcessEditor
export const addDataTypeToAppMetadata = (org: string, app: string, dataTypeId: string, taskId: string) => post(processEditorDataTypePath(org, app, dataTypeId, taskId));
diff --git a/frontend/packages/shared/src/api/paths.js b/frontend/packages/shared/src/api/paths.js
index 49277c5dce8..44753ad07c9 100644
--- a/frontend/packages/shared/src/api/paths.js
+++ b/frontend/packages/shared/src/api/paths.js
@@ -86,9 +86,8 @@ export const languagesPath = (org, app) => `${basePath}/${org}/${app}/languages`
export const orgsListPath = () => `${basePath}/orgs`; // Get
// Preview
-export const instanceIdForPreviewPath = (org, app) => `${basePath}/${org}/${app}/mock-instance-id`; // Get
-export const previewHash = (taskId, selectedLayout) => `#/instance/${PREVIEW_MOCK_PARTY_ID}/${PREVIEW_MOCK_INSTANCE_GUID}/${taskId}/${selectedLayout}`;
-export const previewPage = (org, app, selectedLayoutSet, taskId, selectedLayout) => `/app-specific-preview/${org}/${app}?${s({ selectedLayoutSet })}${taskId && selectedLayout ? previewHash(taskId, selectedLayout) : ''}`;
+export const previewHash = (taskId, selectedLayout, instanceId) => `#/instance/${PREVIEW_MOCK_PARTY_ID}/${instanceId}/${taskId}/${selectedLayout}`;
+export const previewPage = (org, app, selectedLayoutSet, taskId, selectedLayout, instanceId = PREVIEW_MOCK_INSTANCE_GUID) => `/app-specific-preview/${org}/${app}?${s({ selectedLayoutSet })}${taskId && selectedLayout && instanceId ? previewHash(taskId, selectedLayout, instanceId) : ''}`;
// Preview - SignalR Hub
export const previewSignalRHubSubPath = () => `/previewHub`;
@@ -170,6 +169,10 @@ export const resourceAccessListPath = (org, resourceId, listId, env) => `${baseP
export const altinn2DelegationsCountPath = (org, serviceCode, serviceEdition, env) => `${basePath}/${org}/resources/altinn2/delegationcount/${serviceCode}/${serviceEdition}/${env}`; // Get
export const altinn2DelegationsMigrationPath = (org, env) => `${basePath}/${org}/resources/altinn2/delegationmigration/${env}`; // Post
+// Preview
+export const instancesPath = (org, app) => `/${org}/${app}/instances`;
+export const createInstancePath = (org, app, partyId, taskId) => `${instancesPath(org, app)}?instanceOwnerPartyId=${partyId}&taskId=${taskId}`;
+
// Process Editor
export const processEditorPath = (org, app) => `${basePath}/${org}/${app}/process-modelling/process-definition`;
export const processEditorDataTypesChangePath = (org, app) => `${basePath}/${org}/${app}/process-modelling/data-types`;
diff --git a/frontend/packages/shared/src/api/queries.ts b/frontend/packages/shared/src/api/queries.ts
index 786d642aba1..c04ce6d061f 100644
--- a/frontend/packages/shared/src/api/queries.ts
+++ b/frontend/packages/shared/src/api/queries.ts
@@ -14,7 +14,6 @@ import {
envConfigPath,
formLayoutsPath,
frontEndSettingsPath,
- instanceIdForPreviewPath,
layoutSetsPath,
layoutSettingsPath,
optionListIdsPath,
@@ -111,7 +110,6 @@ export const getFormLayouts = (owner: string, app: string, layoutSetName: string
export const getFormLayoutsV3 = (owner: string, app: string, layoutSetName: string) => get(formLayoutsPath(owner, app, layoutSetName));
export const getFrontEndSettings = (owner: string, app: string) => get(frontEndSettingsPath(owner, app));
export const getImageFileNames = (owner: string, app: string) => get(getImageFileNamesPath(owner, app));
-export const getInstanceIdForPreview = (owner: string, app: string) => get(instanceIdForPreviewPath(owner, app));
export const getLayoutNames = (owner: string, app: string) => get(layoutNamesPath(owner, app));
export const getLayoutSets = (owner: string, app: string) => get(layoutSetsPath(owner, app));
export const getLayoutSetsExtended = (owner: string, app: string) => get(layoutSetsPath(owner, app) + '/extended');
diff --git a/frontend/packages/shared/src/hooks/mutations/useCreatePreviewInstanceMutation.ts b/frontend/packages/shared/src/hooks/mutations/useCreatePreviewInstanceMutation.ts
new file mode 100644
index 00000000000..82d77f0d068
--- /dev/null
+++ b/frontend/packages/shared/src/hooks/mutations/useCreatePreviewInstanceMutation.ts
@@ -0,0 +1,15 @@
+import { useMutation } from '@tanstack/react-query';
+import { useServicesContext } from '../../contexts/ServicesContext';
+
+type CreatePreviewPayload = {
+ partyId: number;
+ taskId: string;
+};
+
+export const useCreatePreviewInstanceMutation = (org: string, app: string) => {
+ const { createPreviewInstance } = useServicesContext();
+ return useMutation({
+ mutationFn: ({ partyId, taskId }: CreatePreviewPayload) =>
+ createPreviewInstance(org, app, partyId, taskId),
+ });
+};
diff --git a/frontend/packages/shared/src/hooks/queries/index.ts b/frontend/packages/shared/src/hooks/queries/index.ts
index fc03b8ed37f..0005d1e15d5 100644
--- a/frontend/packages/shared/src/hooks/queries/index.ts
+++ b/frontend/packages/shared/src/hooks/queries/index.ts
@@ -2,7 +2,6 @@ export { useAppMetadataQuery } from './useAppMetadataQuery';
export { useAppVersionQuery } from './useAppVersionQuery';
export { useDataModelsJsonQuery } from './useDataModelsJsonQuery';
export { useDataModelsXsdQuery } from './useDataModelsXsdQuery';
-export { useInstanceIdQuery } from './useInstanceIdQuery';
export { useOptionListQuery } from './useOptionListQuery';
export { useOptionListsQuery } from './useOptionListsQuery';
export { useRepoMetadataQuery } from './useRepoMetadataQuery';
diff --git a/frontend/packages/shared/src/hooks/queries/useInstanceIdQuery.ts b/frontend/packages/shared/src/hooks/queries/useInstanceIdQuery.ts
deleted file mode 100644
index fc5df36f98d..00000000000
--- a/frontend/packages/shared/src/hooks/queries/useInstanceIdQuery.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { UseQueryResult } from '@tanstack/react-query';
-import { useQuery } from '@tanstack/react-query';
-import { QueryKey } from 'app-shared/types/QueryKey';
-import { useServicesContext } from 'app-shared/contexts/ServicesContext';
-
-export const useInstanceIdQuery = (org: string, app: string): UseQueryResult => {
- const { getInstanceIdForPreview } = useServicesContext();
- return useQuery({
- queryKey: [(QueryKey.InstanceId, org, app)],
- queryFn: () => getInstanceIdForPreview(org, app),
- });
-};
diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts
index af2a9364a1e..297a5d6ac59 100644
--- a/frontend/packages/shared/src/mocks/queriesMock.ts
+++ b/frontend/packages/shared/src/mocks/queriesMock.ts
@@ -102,7 +102,6 @@ export const queriesMock: ServicesContextProps = {
getFormLayoutsV3: jest.fn().mockImplementation(() => Promise.resolve({})),
getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})),
getImageFileNames: jest.fn().mockImplementation(() => Promise.resolve([])),
- getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('')),
getLayoutNames: jest.fn().mockImplementation(() => Promise.resolve([])),
getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve