Skip to content

Commit

Permalink
(fix) Resolve Error in JavaScript Expression Validation (#418)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmale authored Oct 28, 2024
1 parent e8b1c5d commit ce3dbdb
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 13 deletions.
54 changes: 54 additions & 0 deletions __mocks__/forms/rfe-forms/js-expression-validation-form.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "Js expression validation",
"uuid": "xxxx",
"EncounterType": "xxxx",
"referencedForms": [],
"processor": "EncounterFormProcessor",
"pages": [
{
"label": "Page 1",
"sections": [
{
"label": "Section 1",
"questions": [
{
"label": "Question 1",
"type": "obs",
"required": false,
"id": "question1",
"questionOptions": {
"rendering": "text",
"concept": "166103AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"conceptMappings": [
{
"relationship": "SAME-AS",
"type": "PIH",
"value": "2724"
},
{
"relationship": "SAME-AS",
"type": "SNOMED CT",
"value": "397678008"
},
{
"relationship": "SAME-AS",
"type": "CIEL",
"value": "166103"
}
],
"showDate": true
},
"validators": [
{
"type": "js_expression",
"failsWhenExpression": "isEmpty(myValue)",
"message": "Empty value not allowed!"
}
]
}
]
}
]
}
]
}
18 changes: 17 additions & 1 deletion src/form-engine.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@openmrs/esm-framework';
import { when } from 'jest-when';
import * as api from './api';
import { assertFormHasAllFields, findCheckboxGroup, findSelectInput } from './utils/test-utils';
import { assertFormHasAllFields, findCheckboxGroup, findSelectInput, findTextOrDateInput } from './utils/test-utils';
import { evaluatePostSubmissionExpression } from './utils/post-submission-action-helper';
import { mockPatient } from '__mocks__/patient.mock';
import { mockSessionDataResponse } from '__mocks__/session.mock';
Expand Down Expand Up @@ -42,6 +42,7 @@ import monthsOnArtForm from '__mocks__/forms/rfe-forms/months-on-art-form.json';
import nextVisitForm from '__mocks__/forms/rfe-forms/next-visit-test-form.json';
import viralLoadStatusForm from '__mocks__/forms/rfe-forms/viral-load-status-form.json';
import readOnlyValidationForm from '__mocks__/forms/rfe-forms/read-only-validation-form.json';
import jsExpressionValidationForm from '__mocks__/forms/rfe-forms/js-expression-validation-form.json';

import FormEngine from './form-engine.component';
import { type SessionMode } from './types';
Expand Down Expand Up @@ -262,6 +263,21 @@ describe('Form engine component', () => {
});
});

describe('js-expression based validation', () => {
it('should invoke validation when field value changes', async () => {
await act(async () => {
renderForm(null, jsExpressionValidationForm);
});

const textField = await findTextOrDateInput(screen, 'Question 1');
await user.type(textField, 'Some value');
// clear value
await user.clear(textField);
const errorMessage = await screen.findByText(/Empty value not allowed!/i);
expect(errorMessage).toBeInTheDocument();
});
});

describe('historical expressions', () => {
it('should ascertain getPreviousEncounter() returns an encounter and the historical expression displays on the UI', async () => {
renderForm(null, historicalExpressionsForm, 'COVID Assessment');
Expand Down
2 changes: 1 addition & 1 deletion src/provider/form-factory-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function validateForm(context: FormContextProps) {
const validator = formFieldValidators[validatorConfig.type];
if (validator) {
const validationResults = validator.validate(field, values[field.id], {
fields: formFields,
formFields,
values,
expressionContext: {
patient,
Expand Down
18 changes: 9 additions & 9 deletions src/validators/js-expression-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ describe('ExpressionValidator - validate', () => {
it('should evaluate js expressions', () => {
// setup
const field = allFields.find((f) => f.id == 'htsProviderRemarks');
const failsWhenExpression = '!isEmpty(myValue) && isEmpty(`referredToPreventionServices`)';
const failsWhenExpression = '!isEmpty(myValue) && isEmpty(referredToPreventionServices)';

// replay
let errors = ExpressionValidator.validate(field, 'Remarks..', {
failsWhenExpression,
expressionContext,
values,
message: 'Atleast one type of Prevention Services must be selected',
fields: allFields,
message: 'At least one type of Prevention Services must be selected',
formFields: allFields,
});

// verify
expect(errors).toEqual([
{
errCode: 'value.invalid',
message: 'Atleast one type of Prevention Services must be selected',
message: 'At least one type of Prevention Services must be selected',
resultType: 'error',
},
]);
Expand All @@ -49,14 +49,14 @@ describe('ExpressionValidator - validate', () => {
expressionContext,
values,
message: 'Atleast one type of Prevention Services must be selected',
fields: allFields,
formFields: allFields,
});

// verify
expect(errors).toEqual([]);
});

fit('should fail if date value is not within the configured bounds', () => {
it('should fail if date value is not within the configured bounds', () => {
// setup
const dateField: FormField = {
label: 'Test Date',
Expand All @@ -81,7 +81,7 @@ describe('ExpressionValidator - validate', () => {
...dateField.validators[0],
expressionContext,
values,
fields: allFields,
formFields: allFields,
});

// verify
Expand All @@ -96,7 +96,7 @@ describe('ExpressionValidator - validate', () => {
...dateField.validators[0],
expressionContext,
values,
fields: allFields,
formFields: allFields,
});

// verify
Expand All @@ -109,7 +109,7 @@ describe('ExpressionValidator - validate', () => {
...dateField.validators[0],
expressionContext,
values,
fields: allFields,
formFields: allFields,
});

// verify
Expand Down
4 changes: 2 additions & 2 deletions src/validators/js-expression-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ interface ExpressionValidatorConfig {
failsWhenExpression?: string;
warnsWhenExpression?: string;
message: string;
fields: FormField[];
formFields: FormField[];
expressionContext: ExpressionContext;
values: Record<string, any>;
}
Expand All @@ -23,7 +23,7 @@ export const ExpressionValidator: FormFieldValidator = {
return evaluateExpression(
config[key],
{ value: field, type: 'field' },
config.fields,
config.formFields,
{ ...config.values, [field.id]: value },
config.expressionContext,
)
Expand Down

0 comments on commit ce3dbdb

Please sign in to comment.