Skip to content

Commit 8683026

Browse files
authored
Feat/expression on validation message (#3454)
* WIP Expression support on validation message * Expression support on validation message * Expression support on validation message * Refactor and add test * Get textresources from many-errors-direct * Get textresources from many-errors-direct
1 parent e4a69f5 commit 8683026

File tree

5 files changed

+28
-18
lines changed

5 files changed

+28
-18
lines changed

src/features/validation/expressionValidation/ExpressionValidation.test.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ExpressionValidation } from 'src/features/validation/expressionValidati
1010
import { Validation } from 'src/features/validation/validationContext';
1111
import { renderWithInstanceAndLayout } from 'src/test/renderWithProviders';
1212
import * as NodesContext from 'src/utils/layout/NodesContext';
13+
import type { IRawTextResource } from 'src/features/language/textResources';
1314
import type { FieldValidations, IExpressionValidationConfig } from 'src/features/validation';
1415
import type { ILayoutCollection } from 'src/layout/layout';
1516

@@ -25,6 +26,7 @@ type ExpressionValidationTest = {
2526
validationConfig: IExpressionValidationConfig;
2627
formData: object;
2728
layouts: ILayoutCollection;
29+
textResources: IRawTextResource[];
2830
};
2931

3032
function sortValidations(validations: SimpleValidation[]) {
@@ -63,7 +65,6 @@ function getSharedTests() {
6365
out.push(test);
6466
}
6567
});
66-
6768
return out;
6869
}
6970

@@ -76,7 +77,7 @@ describe('Expression validation shared tests', () => {
7677
});
7778

7879
const sharedTests = getSharedTests();
79-
it.each(sharedTests)('$name', async ({ name: _, expects, validationConfig, formData, layouts }) => {
80+
it.each(sharedTests)('$name', async ({ name: _, expects, validationConfig, formData, textResources, layouts }) => {
8081
// Mock updateDataModelValidations
8182
let result: FieldValidations = {};
8283
const updateDataModelValidations = jest.fn((_key, _dataType, validations: FieldValidations) => {
@@ -90,6 +91,10 @@ describe('Expression validation shared tests', () => {
9091
fetchLayouts: async () => layouts,
9192
fetchCustomValidationConfig: async () => validationConfig,
9293
fetchFormData: async () => formData,
94+
fetchTextResources: async (language) => ({
95+
language,
96+
resources: textResources ?? [],
97+
}),
9398
},
9499
});
95100

src/features/validation/expressionValidation/ExpressionValidation.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ function IndividualExpressionValidation({ dataType }: { dataType: string }) {
9191
valueArguments,
9292
},
9393
);
94+
const evaluatedMessage = evalExpr(validationDef.message, modifiedDataSources, {
95+
returnType: ExprVal.String,
96+
defaultValue: '',
97+
positionalArguments: [field],
98+
valueArguments,
99+
});
100+
94101
if (isInvalid) {
95102
if (!validations[field]) {
96103
validations[field] = [];
@@ -99,15 +106,14 @@ function IndividualExpressionValidation({ dataType }: { dataType: string }) {
99106
validations[field].push({
100107
field,
101108
source: FrontendValidationSource.Expression,
102-
message: { key: validationDef.message },
109+
message: { key: evaluatedMessage },
103110
severity: validationDef.severity,
104111
category: validationDef.showImmediately ? 0 : ValidationMask.Expression,
105112
});
106113
}
107114
}
108115
}
109116
}
110-
111117
updateDataModelValidations('expression', dataElementId, validations);
112118
}
113119
}, [

src/features/validation/expressionValidation/shared-expression-validation-tests/many-errors-direct.json

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"componentId": "name-input"
1515
},
1616
{
17-
"message": "email must be real",
17+
"message": "The typed email must be real",
1818
"severity": "error",
1919
"field": "form.email",
2020
"componentId": "email-input"
@@ -41,17 +41,13 @@
4141
"form.email": [
4242
"none-is-not-allowed",
4343
{
44-
"message": "email must be real",
44+
"message": ["text", "email-must-be-real"],
4545
"severity": "error",
4646
"condition": ["contains", ["dataModel", "form.email"], "fake"]
4747
},
4848
{
4949
"ref": "str-len",
50-
"condition": [
51-
"lessThan",
52-
["stringLength", ["dataModel", "form.email"]],
53-
20
54-
]
50+
"condition": ["lessThan", ["stringLength", ["dataModel", "form.email"]], 20]
5551
},
5652
{
5753
"message": "email must contain @",
@@ -69,11 +65,7 @@
6965
"str-len": {
7066
"message": "string is too short",
7167
"severity": "error",
72-
"condition": [
73-
"lessThan",
74-
["stringLength", ["dataModel", ["argv", 0]]],
75-
5
76-
]
68+
"condition": ["lessThan", ["stringLength", ["dataModel", ["argv", 0]]], 5]
7769
}
7870
}
7971
},
@@ -83,6 +75,12 @@
8375
"email": "[email protected]"
8476
}
8577
},
78+
"textResources": [
79+
{
80+
"id": "email-must-be-real",
81+
"value": "The typed email must be real"
82+
}
83+
],
8684
"layouts": {
8785
"Page": {
8886
"$schema": "https://altinncdn.no/schemas/json/layout/layout.schema.v1.json",

src/features/validation/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Expression, ExprValToActual } from 'src/features/expressions/types';
1+
import type { Expression, ExprVal, ExprValToActual, ExprValToActualOrExpr } from 'src/features/expressions/types';
22
import type { TextReference, ValidLangParam } from 'src/features/language/useLanguage';
33
import type { LayoutNode } from 'src/utils/layout/LayoutNode';
44

@@ -229,7 +229,7 @@ export interface BackendValidationIssue {
229229
* Expression validation object.
230230
*/
231231
export type IExpressionValidation = {
232-
message: string;
232+
message: ExprValToActualOrExpr<ExprVal.String>;
233233
condition: Expression | ExprValToActual;
234234
severity: ValidationSeverity;
235235
showImmediately: boolean;

src/layout/GenericComponent.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ function NonMemoGenericComponent<Type extends CompTypes = CompTypes>({
6060
}: IGenericComponentProps<Type>) {
6161
const itemExists = useNodeItem(node, (i) => !!i);
6262
const generatorErrors = NodesInternal.useNodeData(node, (node) => node.errors);
63+
6364
if (generatorErrors && Object.keys(generatorErrors).length > 0) {
6465
return (
6566
<ErrorList

0 commit comments

Comments
 (0)