-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui-editor): add lookup components #14516
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Net; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Net.Http; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Threading.Tasks; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Mvc.Testing; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Xunit; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Designer.Tests.Controllers.PreviewController | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public class OrganisationLookupTests : PreviewControllerTestsBase<OrganisationLookupTests>, IClassFixture<WebApplicationFactory<Program>> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
protected const string organisationNumber = "123456789"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public OrganisationLookupTests(WebApplicationFactory<Program> factory) : base(factory) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task Get_OrganisationLookup_Ok() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/organisation/{organisationNumber}"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
string responseBody = await response.Content.ReadAsStringAsync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Assert.Contains(organisationNumber, responseBody); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Assert.Contains("Test AS", responseBody); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+18
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage with additional scenarios. Similar to PersonLookupTests, consider adding tests for:
Example test case: [Theory]
[InlineData("12345")] // Too short
[InlineData("1234567890")] // Too long
[InlineData("abcdefghi")] // Non-numeric
public async Task Get_OrganisationLookup_InvalidNumber_ReturnsBadRequest(string invalidNumber)
{
string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/organisation/{invalidNumber}";
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.BadRequest, response.StatusCode);
}
Comment on lines
+18
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage with additional test cases. The current test only covers the happy path. Consider adding:
+ [Fact]
+ public async Task Get_OrganisationLookup_InvalidFormat_ReturnsBadRequest()
+ {
+ string invalidOrgNumber = "invalid";
+ string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/organisation/{invalidOrgNumber}";
+ 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.BadRequest, response.StatusCode);
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc.Testing; | ||
using Xunit; | ||
|
||
namespace Designer.Tests.Controllers.PreviewController | ||
{ | ||
public class PersonLookupTests : PreviewControllerTestsBase<PersonLookupTests>, IClassFixture<WebApplicationFactory<Program>> | ||
{ | ||
|
||
public PersonLookupTests(WebApplicationFactory<Program> factory) : base(factory) | ||
{ | ||
} | ||
|
||
[Fact] | ||
public async Task Post_PersonLookup_Ok() | ||
{ | ||
string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/person"; | ||
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, 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); | ||
|
||
string responseBody = await response.Content.ReadAsStringAsync(); | ||
Assert.Contains("Test T. Testesen", responseBody); | ||
} | ||
Comment on lines
+17
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add test coverage for error scenarios. The current test only covers the successful case. Consider adding tests for:
Example test case: [Fact]
public async Task Post_PersonLookup_MissingReferrer_ReturnsBadRequest()
{
string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/person";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
// No referrer header set
using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
Comment on lines
+17
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage with additional test cases. The current test only covers the happy path. Consider adding:
+ [Fact]
+ public async Task Post_PersonLookup_InvalidRequest_ReturnsBadRequest()
+ {
+ string dataPathWithData = $"{Org}/{AppV4}/api/v1/lookup/person";
+ using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
+ httpRequestMessage.Content = new StringContent("invalid_request_body");
+
+ using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
+ Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
+ }
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
{ | ||
"$id": "https://altinncdn.no/schemas/json/component/OrganisationLookup.schema.v1.json", | ||
"$schema": "http://json-schema.org/draft-07/schema#", | ||
"properties": { | ||
"id": { | ||
"title": "ID", | ||
"description": "The component ID. Must be unique within all layouts/pages in a layout-set. Cannot end with <dash><number>.", | ||
"type": "string", | ||
"pattern": "^[0-9a-zA-Z][0-9a-zA-Z-]*(-?[a-zA-Z]+|[a-zA-Z][0-9]+|-[0-9]{6,})$" | ||
}, | ||
"hidden": { | ||
"title": "Hidden", | ||
"description": "Boolean value or expression indicating if the component should be hidden. Defaults to false.", | ||
"default": false, | ||
"$ref": "expression.schema.v1.json#/definitions/boolean" | ||
}, | ||
"grid": { | ||
"properties": { | ||
"xs": { "default": "auto", "$ref": "#/definitions/IGridSize" }, | ||
"sm": { "default": "auto", "$ref": "#/definitions/IGridSize" }, | ||
"md": { "default": "auto", "$ref": "#/definitions/IGridSize" }, | ||
"lg": { "default": "auto", "$ref": "#/definitions/IGridSize" }, | ||
"xl": { "default": "auto", "$ref": "#/definitions/IGridSize" }, | ||
"labelGrid": { "$ref": "#/definitions/IGridStyling" }, | ||
"innerGrid": { "$ref": "#/definitions/IGridStyling" } | ||
} | ||
}, | ||
"pageBreak": { | ||
"title": "Page break", | ||
"description": "Optionally insert page-break before/after component when rendered in PDF", | ||
"type": "object", | ||
"properties": { | ||
"breakBefore": { | ||
"title": "Page break before", | ||
"description": "PDF only: Value or expression indicating whether a page break should be added before the component. Can be either: 'auto' (default), 'always', or 'avoid'.", | ||
"examples": ["auto", "always", "avoid"], | ||
"default": "auto", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"breakAfter": { | ||
"title": "Page break after", | ||
"description": "PDF only: Value or expression indicating whether a page break should be added after the component. Can be either: 'auto' (default), 'always', or 'avoid'.", | ||
"examples": ["auto", "always", "avoid"], | ||
"default": "auto", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
} | ||
}, | ||
"additionalProperties": false | ||
}, | ||
"readOnly": { | ||
"title": "Read only/disabled?", | ||
"description": "Boolean value or expression indicating if the component should be read only/disabled. Defaults to false. <br /> <i>Please note that even with read-only fields in components, it may currently be possible to update the field by modifying the request sent to the API or through a direct API call.<i/>", | ||
"default": false, | ||
"$ref": "expression.schema.v1.json#/definitions/boolean" | ||
}, | ||
"required": { | ||
"title": "Required?", | ||
"description": "Boolean value or expression indicating if the component should be required. Defaults to false.", | ||
"default": false, | ||
"$ref": "expression.schema.v1.json#/definitions/boolean" | ||
}, | ||
"showValidations": { | ||
"title": "Validation types", | ||
"description": "List of validation types to show", | ||
"type": "array", | ||
"items": { | ||
"enum": [ | ||
"Schema", | ||
"Component", | ||
"Expression", | ||
"CustomBackend", | ||
"Required", | ||
"AllExceptRequired", | ||
"All" | ||
], | ||
"type": "string" | ||
} | ||
}, | ||
"renderAsSummary": { | ||
"title": "Render as summary", | ||
"description": "Boolean value indicating if the component should be rendered as a summary. Defaults to false.", | ||
"default": false, | ||
"type": "boolean" | ||
}, | ||
"forceShowInSummary": { | ||
"title": "Force show in summary", | ||
"description": "Will force show the component in a summary even if hideEmptyFields is set to true in the summary component.", | ||
"default": false, | ||
"$ref": "expression.schema.v1.json#/definitions/boolean" | ||
}, | ||
"type": { "const": "OrganisationLookup" }, | ||
"textResourceBindings": { | ||
"properties": { | ||
"title": { | ||
"title": "Title", | ||
"description": "The title of the component", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"description": { | ||
"title": "Description", | ||
"description": "Description, optionally shown below the title", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"help": { | ||
"title": "Help Text", | ||
"description": "Help text, optionally shown next to the title", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"tableTitle": { | ||
"title": "Table title", | ||
"description": "Title used in the table view (overrides the default title)", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"shortName": { | ||
"title": "Short name (for validation)", | ||
"description": "Alternative name used for required validation messages (overrides the default title)", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"requiredValidation": { | ||
"title": "Required validation message", | ||
"description": "Full validation message shown when the component is required and no value has been entered (overrides both the default and shortName)", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"summaryTitle": { | ||
"title": "Summary title", | ||
"description": "Title used in the summary view (overrides the default title)", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
}, | ||
"summaryAccessibleTitle": { | ||
"title": "Accessible summary title", | ||
"description": "Title used for aria-label on the edit button in the summary view (overrides the default and summary title)", | ||
"$ref": "expression.schema.v1.json#/definitions/string" | ||
} | ||
} | ||
}, | ||
"dataModelBindings": { | ||
"type": "object", | ||
"properties": { | ||
"organisation_lookup_orgnr": { "$ref": "#/definitions/IRawDataModelBinding" }, | ||
"organisation_lookup_name": { "$ref": "#/definitions/IRawDataModelBinding" } | ||
}, | ||
"required": ["organisation_lookup_orgnr"], | ||
"additionalProperties": false | ||
} | ||
}, | ||
"required": ["id", "type", "dataModelBindings"], | ||
"title": "OrganisationLookup component schema" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance the person lookup endpoint with request validation and error handling.
Consider the following improvements:
📝 Committable suggestion