@openmrs/esm-form-engine-lib 2.1.0-pre.1502 → 2.1.0-pre.1511
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/3a3e1d216bd6470d/3a3e1d216bd6470d.gz +0 -0
- package/__mocks__/forms/rfe-forms/bmi-test-form.json +66 -66
- package/__mocks__/forms/rfe-forms/bsa-test-form.json +66 -66
- package/__mocks__/forms/rfe-forms/edd-test-form.json +87 -87
- package/__mocks__/forms/rfe-forms/external_data_source_form.json +35 -36
- package/__mocks__/forms/rfe-forms/historical-expressions-form.json +1 -1
- package/__mocks__/forms/rfe-forms/labour_and_delivery_test_form.json +1 -1
- package/__mocks__/forms/rfe-forms/months-on-art-form.json +89 -89
- package/__mocks__/forms/rfe-forms/next-visit-test-form.json +77 -77
- package/b3059e748360776a/b3059e748360776a.gz +0 -0
- package/dist/openmrs-esm-form-engine-lib.js +1 -1
- package/package.json +1 -1
- package/src/components/inputs/date/date.test.tsx +107 -0
- package/src/components/inputs/number/number.component.tsx +2 -1
- package/src/components/inputs/ui-select-extended/ui-select-extended.component.tsx +1 -1
- package/src/components/inputs/ui-select-extended/ui-select-extended.test.tsx +5 -0
- package/src/processors/encounter/encounter-form-processor.ts +13 -14
- package/src/types/schema.ts +0 -2
- package/src/utils/common-expression-helpers.test.ts +74 -5
- package/src/utils/common-expression-helpers.ts +21 -26
- package/src/utils/expression-runner.test.ts +156 -69
- package/src/utils/expression-runner.ts +85 -135
- package/aaf8197a12df0c40/aaf8197a12df0c40.gz +0 -0
- package/aba5c979c0dbf1c7/aba5c979c0dbf1c7.gz +0 -0
- package/src/utils/expression-parser.test.ts +0 -308
- package/src/utils/expression-parser.ts +0 -158
- /package/{47245761e3f779c4/47245761e3f779c4.gz → 22ec231da647cd2c/22ec231da647cd2c.gz} +0 -0
- /package/{6f1d94035d69e5e1/6f1d94035d69e5e1.gz → 485e0040f135cee8/485e0040f135cee8.gz} +0 -0
@@ -1,15 +1,36 @@
|
|
1
1
|
import dayjs from 'dayjs';
|
2
|
-
import { CommonExpressionHelpers } from './common-expression-helpers';
|
2
|
+
import { CommonExpressionHelpers, simpleHash } from './common-expression-helpers';
|
3
|
+
import { type FormField } from '../types';
|
3
4
|
|
4
5
|
describe('CommonExpressionHelpers', () => {
|
5
6
|
let helpers: CommonExpressionHelpers;
|
6
7
|
const mockPatient = { birthDate: '1990-01-01', sex: 'male' };
|
7
|
-
const mockFields = [
|
8
|
+
const mockFields: Array<FormField> = [
|
9
|
+
{
|
10
|
+
label: 'Question 1',
|
11
|
+
type: 'obs',
|
12
|
+
questionOptions: {
|
13
|
+
rendering: 'radio',
|
14
|
+
concept: 'question1_concept',
|
15
|
+
answers: [],
|
16
|
+
},
|
17
|
+
id: 'question1',
|
18
|
+
},
|
19
|
+
{
|
20
|
+
label: 'Question 2',
|
21
|
+
type: 'obs',
|
22
|
+
questionOptions: {
|
23
|
+
rendering: 'radio',
|
24
|
+
concept: 'question2_concept',
|
25
|
+
answers: [],
|
26
|
+
},
|
27
|
+
id: 'question2',
|
28
|
+
},
|
29
|
+
];
|
8
30
|
const mockFieldValues = {};
|
9
|
-
const mockFieldKeys = [];
|
10
31
|
|
11
32
|
beforeEach(() => {
|
12
|
-
helpers = new CommonExpressionHelpers(null, mockPatient, mockFields, mockFieldValues
|
33
|
+
helpers = new CommonExpressionHelpers(null, mockPatient, mockFields, mockFieldValues);
|
13
34
|
});
|
14
35
|
|
15
36
|
describe('isEmpty', () => {
|
@@ -86,13 +107,25 @@ describe('CommonExpressionHelpers', () => {
|
|
86
107
|
describe('useFieldValue', () => {
|
87
108
|
it('should return the field value if the key exists', () => {
|
88
109
|
helpers.allFieldValues = { question1: 'value1' };
|
89
|
-
helpers.allFieldsKeys = ['question1'];
|
90
110
|
expect(helpers.useFieldValue('question1')).toBe('value1');
|
91
111
|
});
|
92
112
|
|
93
113
|
it('should return null if the key does not exist', () => {
|
94
114
|
expect(helpers.useFieldValue('question2')).toBe(null);
|
95
115
|
});
|
116
|
+
|
117
|
+
it("should register dependency of the current node to it's determinant", () => {
|
118
|
+
// question1 as the current node
|
119
|
+
helpers.node = {
|
120
|
+
value: mockFields[0],
|
121
|
+
type: 'field',
|
122
|
+
};
|
123
|
+
helpers.allFieldValues = { question1: 'value1', question2: 'value2' };
|
124
|
+
|
125
|
+
helpers.useFieldValue('question2');
|
126
|
+
// assert that question2 lists question1 as dependent
|
127
|
+
expect(Array.from(mockFields[1].fieldDependents)).toStrictEqual(['question1']);
|
128
|
+
});
|
96
129
|
});
|
97
130
|
|
98
131
|
describe('doesNotMatchExpression', () => {
|
@@ -329,3 +362,39 @@ describe('CommonExpressionHelpers', () => {
|
|
329
362
|
});
|
330
363
|
});
|
331
364
|
});
|
365
|
+
|
366
|
+
describe('simpleHash', () => {
|
367
|
+
test('should return the same hash for the same input string', () => {
|
368
|
+
const expression = "linkedToCare == '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
369
|
+
const hash1 = simpleHash(expression);
|
370
|
+
const hash2 = simpleHash(expression);
|
371
|
+
expect(hash1).toBe(hash2);
|
372
|
+
});
|
373
|
+
|
374
|
+
test('should return different hashes for different input strings', () => {
|
375
|
+
const expression1 = "linkedToCare == '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
376
|
+
const expression2 = "linkedToCare !== '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
377
|
+
const hash1 = simpleHash(expression1);
|
378
|
+
const hash2 = simpleHash(expression2);
|
379
|
+
expect(hash1).not.toBe(hash2);
|
380
|
+
});
|
381
|
+
|
382
|
+
test('should handle empty string and return 0', () => {
|
383
|
+
const expression = '';
|
384
|
+
const hash = simpleHash(expression);
|
385
|
+
expect(hash).toBe(0);
|
386
|
+
});
|
387
|
+
|
388
|
+
test('should handle long strings without errors', () => {
|
389
|
+
const longExpression = 'left != right &'.repeat(1000);
|
390
|
+
const hash = simpleHash(longExpression);
|
391
|
+
expect(hash).toBeDefined();
|
392
|
+
});
|
393
|
+
|
394
|
+
test('should return consistent hash for strings with Unicode characters', () => {
|
395
|
+
const str = '😊💻';
|
396
|
+
const hash1 = simpleHash(str);
|
397
|
+
const hash2 = simpleHash(str);
|
398
|
+
expect(hash1).toBe(hash2);
|
399
|
+
});
|
400
|
+
});
|
@@ -11,7 +11,6 @@ import { type FormNode } from './expression-runner';
|
|
11
11
|
import { isEmpty as isValueEmpty } from '../validators/form-validator';
|
12
12
|
import * as apiFunctions from '../api';
|
13
13
|
import { getZRefByGenderAndAge } from './zscore-service';
|
14
|
-
import { ConceptFalse, ConceptTrue } from '../constants';
|
15
14
|
import { formatDate, parseDate } from '@openmrs/esm-framework';
|
16
15
|
|
17
16
|
export class CommonExpressionHelpers {
|
@@ -19,20 +18,12 @@ export class CommonExpressionHelpers {
|
|
19
18
|
patient: any = null;
|
20
19
|
allFields: FormField[] = [];
|
21
20
|
allFieldValues: Record<string, any> = {};
|
22
|
-
allFieldsKeys: string[] = [];
|
23
21
|
api = apiFunctions;
|
24
22
|
isEmpty = isValueEmpty;
|
25
23
|
|
26
|
-
constructor(
|
27
|
-
node: FormNode,
|
28
|
-
patient: any,
|
29
|
-
allFields: FormField[],
|
30
|
-
allFieldValues: Record<string, any>,
|
31
|
-
allFieldsKeys: string[],
|
32
|
-
) {
|
24
|
+
constructor(node: FormNode, patient: any, allFields: FormField[], allFieldValues: Record<string, any>) {
|
33
25
|
this.allFields = allFields;
|
34
26
|
this.allFieldValues = allFieldValues;
|
35
|
-
this.allFieldsKeys = allFieldsKeys;
|
36
27
|
this.node = node;
|
37
28
|
this.patient = patient;
|
38
29
|
}
|
@@ -88,10 +79,12 @@ export class CommonExpressionHelpers {
|
|
88
79
|
};
|
89
80
|
|
90
81
|
useFieldValue = (questionId: string) => {
|
91
|
-
|
92
|
-
|
82
|
+
const targetField = this.allFields.find((field) => field.id === questionId);
|
83
|
+
if (targetField) {
|
84
|
+
// track field dependency
|
85
|
+
registerDependency(this.node, targetField);
|
93
86
|
}
|
94
|
-
return null;
|
87
|
+
return this.allFieldValues[questionId] ?? null;
|
95
88
|
};
|
96
89
|
|
97
90
|
doesNotMatchExpression = (regexString: string, val: string | null | undefined): boolean => {
|
@@ -473,6 +466,21 @@ export class CommonExpressionHelpers {
|
|
473
466
|
};
|
474
467
|
}
|
475
468
|
|
469
|
+
/**
|
470
|
+
* Simple hash function to generate a unique identifier for a string.
|
471
|
+
* @param str - The string to hash.
|
472
|
+
* @returns A unique identifier for the string.
|
473
|
+
*/
|
474
|
+
export function simpleHash(str: string) {
|
475
|
+
let hash = 0;
|
476
|
+
for (let i = 0; i < str.length; i++) {
|
477
|
+
const char = str.charCodeAt(i);
|
478
|
+
hash = (hash << 5) - hash + char;
|
479
|
+
hash |= 0;
|
480
|
+
}
|
481
|
+
return hash;
|
482
|
+
}
|
483
|
+
|
476
484
|
export function registerDependency(node: FormNode, determinant: FormField) {
|
477
485
|
if (!node || !determinant) {
|
478
486
|
return;
|
@@ -497,16 +505,3 @@ export function registerDependency(node: FormNode, determinant: FormField) {
|
|
497
505
|
determinant.fieldDependents.add(node.value['id']);
|
498
506
|
}
|
499
507
|
}
|
500
|
-
|
501
|
-
export const booleanConceptToBoolean = (booleanConceptRepresentation): boolean => {
|
502
|
-
const { value } = booleanConceptRepresentation;
|
503
|
-
if (!booleanConceptRepresentation) {
|
504
|
-
throw new Error('booleanConceptRepresentation cannot be a null value');
|
505
|
-
}
|
506
|
-
if (value == ConceptTrue) {
|
507
|
-
return true;
|
508
|
-
}
|
509
|
-
if (value == ConceptFalse) {
|
510
|
-
return false;
|
511
|
-
}
|
512
|
-
};
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { registerExpressionHelper } from '..';
|
2
2
|
import { type FormField } from '../types';
|
3
|
-
import {
|
4
|
-
import { checkReferenceToResolvedFragment, evaluateExpression, type ExpressionContext } from './expression-runner';
|
3
|
+
import { evaluateAsyncExpression, evaluateExpression, type ExpressionContext } from './expression-runner';
|
5
4
|
|
6
5
|
export const testFields: Array<FormField> = [
|
7
6
|
{
|
@@ -79,7 +78,100 @@ export const testFields: Array<FormField> = [
|
|
79
78
|
},
|
80
79
|
];
|
81
80
|
|
82
|
-
|
81
|
+
export const fields: Array<FormField> = [
|
82
|
+
{
|
83
|
+
label: 'No Interest',
|
84
|
+
type: 'obs',
|
85
|
+
questionOptions: {
|
86
|
+
rendering: 'radio',
|
87
|
+
concept: 'no_interest_concept',
|
88
|
+
answers: [],
|
89
|
+
},
|
90
|
+
id: 'no_interest',
|
91
|
+
},
|
92
|
+
{
|
93
|
+
label: 'Depressed',
|
94
|
+
type: 'obs',
|
95
|
+
questionOptions: {
|
96
|
+
rendering: 'radio',
|
97
|
+
concept: 'depressed_concept',
|
98
|
+
answers: [],
|
99
|
+
},
|
100
|
+
id: 'depressed',
|
101
|
+
},
|
102
|
+
{
|
103
|
+
label: 'Bad Sleep',
|
104
|
+
type: 'obs',
|
105
|
+
questionOptions: {
|
106
|
+
rendering: 'radio',
|
107
|
+
concept: 'bad_sleep_concept',
|
108
|
+
answers: [],
|
109
|
+
},
|
110
|
+
id: 'bad_sleep',
|
111
|
+
},
|
112
|
+
{
|
113
|
+
label: 'Feeling Tired',
|
114
|
+
type: 'obs',
|
115
|
+
questionOptions: {
|
116
|
+
rendering: 'radio',
|
117
|
+
concept: 'feeling_tired_concept',
|
118
|
+
answers: [],
|
119
|
+
},
|
120
|
+
id: 'feeling_tired',
|
121
|
+
},
|
122
|
+
{
|
123
|
+
label: 'Poor Appetite',
|
124
|
+
type: 'obs',
|
125
|
+
questionOptions: {
|
126
|
+
rendering: 'radio',
|
127
|
+
concept: 'poor_appetite_concept',
|
128
|
+
answers: [],
|
129
|
+
},
|
130
|
+
id: 'poor_appetite',
|
131
|
+
},
|
132
|
+
{
|
133
|
+
label: 'Troubled',
|
134
|
+
type: 'obs',
|
135
|
+
questionOptions: {
|
136
|
+
rendering: 'radio',
|
137
|
+
concept: 'troubled_concept',
|
138
|
+
answers: [],
|
139
|
+
},
|
140
|
+
id: 'troubled',
|
141
|
+
},
|
142
|
+
{
|
143
|
+
label: 'Feeling Bad',
|
144
|
+
type: 'obs',
|
145
|
+
questionOptions: {
|
146
|
+
rendering: 'radio',
|
147
|
+
concept: 'feeling_bad_concept',
|
148
|
+
answers: [],
|
149
|
+
},
|
150
|
+
id: 'feeling_bad',
|
151
|
+
},
|
152
|
+
{
|
153
|
+
label: 'Speaking Slowly',
|
154
|
+
type: 'obs',
|
155
|
+
questionOptions: {
|
156
|
+
rendering: 'radio',
|
157
|
+
concept: 'speaking_slowly_concept',
|
158
|
+
answers: [],
|
159
|
+
},
|
160
|
+
id: 'speaking_slowly',
|
161
|
+
},
|
162
|
+
{
|
163
|
+
label: 'Better Off Dead',
|
164
|
+
type: 'obs',
|
165
|
+
questionOptions: {
|
166
|
+
rendering: 'radio',
|
167
|
+
concept: 'better_dead_concept',
|
168
|
+
answers: [],
|
169
|
+
},
|
170
|
+
id: 'better_dead',
|
171
|
+
},
|
172
|
+
];
|
173
|
+
|
174
|
+
describe('Expression runner', () => {
|
83
175
|
const context: ExpressionContext = { mode: 'enter', patient: {} };
|
84
176
|
const allFields = JSON.parse(JSON.stringify(testFields));
|
85
177
|
let valuesMap = {
|
@@ -88,6 +180,15 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
88
180
|
htsProviderRemarks: '',
|
89
181
|
referredToPreventionServices: [],
|
90
182
|
bodyTemperature: 0,
|
183
|
+
no_interest: '',
|
184
|
+
depressed: '',
|
185
|
+
bad_sleep: '',
|
186
|
+
feeling_tired: '',
|
187
|
+
poor_appetite: '',
|
188
|
+
troubled: '',
|
189
|
+
feeling_bad: '',
|
190
|
+
speaking_slowly: '',
|
191
|
+
better_dead: '',
|
91
192
|
};
|
92
193
|
|
93
194
|
afterEach(() => {
|
@@ -98,24 +199,37 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
98
199
|
htsProviderRemarks: '',
|
99
200
|
referredToPreventionServices: [],
|
100
201
|
bodyTemperature: 0,
|
202
|
+
no_interest: '',
|
203
|
+
depressed: '',
|
204
|
+
bad_sleep: '',
|
205
|
+
feeling_tired: '',
|
206
|
+
poor_appetite: '',
|
207
|
+
troubled: '',
|
208
|
+
feeling_bad: '',
|
209
|
+
speaking_slowly: '',
|
210
|
+
better_dead: '',
|
101
211
|
};
|
102
212
|
allFields.forEach((field) => {
|
103
213
|
field.fieldDependents = undefined;
|
104
214
|
});
|
105
215
|
});
|
106
216
|
|
107
|
-
it('should
|
217
|
+
it('should support unary expressions', () => {
|
108
218
|
// replay and verify
|
109
219
|
expect(
|
110
220
|
evaluateExpression('true', { value: allFields[0], type: 'field' }, allFields, valuesMap, context),
|
111
221
|
).toBeTruthy();
|
112
222
|
// replay and verify
|
113
223
|
expect(
|
114
|
-
evaluateExpression('
|
224
|
+
evaluateExpression('!true', { value: allFields[0], type: 'field' }, allFields, valuesMap, context),
|
115
225
|
).toBeFalsy();
|
226
|
+
// replay and verify
|
227
|
+
expect(
|
228
|
+
evaluateExpression('!false', { value: allFields[0], type: 'field' }, allFields, valuesMap, context),
|
229
|
+
).toBeTruthy();
|
116
230
|
});
|
117
231
|
|
118
|
-
it('should support
|
232
|
+
it('should support binary expressions', () => {
|
119
233
|
// replay and verify
|
120
234
|
expect(
|
121
235
|
evaluateExpression(
|
@@ -140,46 +254,42 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
140
254
|
).toBeTruthy();
|
141
255
|
});
|
142
256
|
|
143
|
-
it('should support
|
144
|
-
//
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
// replay and verify
|
159
|
-
expect(
|
160
|
-
evaluateExpression(
|
161
|
-
"linkedToCare == 'cf82933b-3f3f-45e7-a5ab-5d31aaee3da3' && htsProviderRemarks !== '' && bodyTemperature >= 39",
|
162
|
-
{ value: allFields[1], type: 'field' },
|
163
|
-
allFields,
|
164
|
-
valuesMap,
|
165
|
-
context,
|
166
|
-
),
|
167
|
-
).toBeTruthy();
|
257
|
+
it('should support complex expressions', () => {
|
258
|
+
// setup
|
259
|
+
valuesMap.bad_sleep = 'a53f32bc-6904-4692-8a4c-fb7403cf0306';
|
260
|
+
valuesMap.better_dead = '296b39ec-06c5-4310-8f30-d2c9f083fb71';
|
261
|
+
valuesMap.depressed = '5eb5852d-3d29-41f9-b2ff-d194e062003d';
|
262
|
+
valuesMap.feeling_bad = '349260db-8e0f-4c06-be92-5120b3708d1e';
|
263
|
+
valuesMap.feeling_tired = '0ea1378d-04eb-4e7e-908b-26d8c27d37e1';
|
264
|
+
valuesMap.troubled = '57766c65-6548-486b-9dad-0fedf531ed7d';
|
265
|
+
|
266
|
+
const expression =
|
267
|
+
"(no_interest === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : isEmpty(no_interest) ? 2 : no_interest === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (depressed === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : depressed === '5eb5852d-3d29-41f9-b2ff-d194e062003d' ? 2 : depressed==='8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (bad_sleep === 'a53f32bc-6904-4692-8a4c-fb7403cf0306' ? 1 : bad_sleep === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : bad_sleep === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (feeling_tired === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : feeling_tired === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : feeling_tired === '0ea1378d-04eb-4e7e-908b-26d8c27d37e1' ? 3 : 0) +(poor_appetite === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : poor_appetite === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : poor_appetite === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (troubled === '57766c65-6548-486b-9dad-0fedf531ed7d' ? 1 : troubled === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : troubled === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (feeling_bad === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : feeling_bad === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : feeling_bad === '349260db-8e0f-4c06-be92-5120b3708d1e' ? 3 : 0) + (speaking_slowly === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : speaking_slowly === '234259ec-5368-4488-8482-4f261cc76714' ? 2 : speaking_slowly === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0) + (better_dead === 'b631d160-8d40-4cf7-92cd-67f628c889e8' ? 1 : better_dead === '296b39ec-06c5-4310-8f30-d2c9f083fb71' ? 2 : better_dead === '8ff1f85c-4f04-4f5b-936a-5aa9320cb66e' ? 3 : 0)";
|
268
|
+
|
269
|
+
expect(evaluateExpression(expression, { value: allFields[9], type: 'field' }, allFields, valuesMap, context)).toBe(
|
270
|
+
14,
|
271
|
+
);
|
168
272
|
});
|
169
273
|
|
170
|
-
it('should support
|
274
|
+
it('should support async expressions', async () => {
|
171
275
|
// setup
|
172
|
-
valuesMap
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
276
|
+
valuesMap.bad_sleep = 'a53f32bc-6904-4692-8a4c-fb7403cf0306';
|
277
|
+
registerExpressionHelper('getAsyncValue', () => {
|
278
|
+
return new Promise((resolve) => {
|
279
|
+
setTimeout(() => {
|
280
|
+
resolve(18);
|
281
|
+
}, 10);
|
282
|
+
});
|
283
|
+
});
|
284
|
+
|
285
|
+
const result = await evaluateAsyncExpression(
|
286
|
+
'getAsyncValue().then(value => !isEmpty(bad_sleep) ? value + 3 : value)',
|
287
|
+
{ value: allFields[9], type: 'field' },
|
288
|
+
allFields,
|
289
|
+
valuesMap,
|
290
|
+
context,
|
291
|
+
);
|
292
|
+
expect(result).toBe(21);
|
183
293
|
});
|
184
294
|
|
185
295
|
it('should support includes(question, value) runtime helper function', () => {
|
@@ -191,7 +301,7 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
191
301
|
// replay and verify
|
192
302
|
expect(
|
193
303
|
evaluateExpression(
|
194
|
-
"includes(
|
304
|
+
"includes(referredToPreventionServices, '88cdde2b-753b-48ac-a51a-ae5e1ab24846') && !includes(referredToPreventionServices, '1691AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')",
|
195
305
|
{ value: allFields[1], type: 'field' },
|
196
306
|
allFields,
|
197
307
|
valuesMap,
|
@@ -203,7 +313,7 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
203
313
|
it('should support session mode as a runtime', () => {
|
204
314
|
expect(
|
205
315
|
evaluateExpression(
|
206
|
-
"mode == 'enter' && isEmpty(
|
316
|
+
"mode == 'enter' && isEmpty(htsProviderRemarks)",
|
207
317
|
{ value: allFields[2], type: 'field' },
|
208
318
|
allFields,
|
209
319
|
valuesMap,
|
@@ -222,7 +332,7 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
222
332
|
// replay
|
223
333
|
expect(
|
224
334
|
evaluateExpression(
|
225
|
-
"!includes(
|
335
|
+
"!includes(referredToPreventionServices, '88cdde2b-753b-48ac-a51a-ae5e1ab24846') && isEmpty(htsProviderRemarks)",
|
226
336
|
{ value: allFields[4], type: 'field' },
|
227
337
|
allFields,
|
228
338
|
valuesMap,
|
@@ -251,26 +361,3 @@ describe('Common expression runner - evaluateExpression', () => {
|
|
251
361
|
expect(result).toEqual(5);
|
252
362
|
});
|
253
363
|
});
|
254
|
-
|
255
|
-
describe('Common expression runner - checkReferenceToResolvedFragment', () => {
|
256
|
-
it('should extract resolved fragment and chained reference when given a valid input', () => {
|
257
|
-
const token = 'resolve(api.fetchSomeValue("arg1", "arg2")).someOtherRef';
|
258
|
-
const expected = ['resolve(api.fetchSomeValue("arg1", "arg2"))', '.someOtherRef'];
|
259
|
-
const result = checkReferenceToResolvedFragment(token);
|
260
|
-
expect(result).toEqual(expected);
|
261
|
-
});
|
262
|
-
|
263
|
-
it('should extract only resolved fragment when there is no chained reference', () => {
|
264
|
-
const token = 'resolve(AnotherFragment)';
|
265
|
-
const expected = ['resolve(AnotherFragment)', ''];
|
266
|
-
const result = checkReferenceToResolvedFragment(token);
|
267
|
-
expect(result).toEqual(expected);
|
268
|
-
});
|
269
|
-
|
270
|
-
it('should return an empty string for the resolved fragment and chained reference when given an invalid input', () => {
|
271
|
-
const token = 'invalidToken';
|
272
|
-
const expected = ['', ''];
|
273
|
-
const result = checkReferenceToResolvedFragment(token);
|
274
|
-
expect(result).toEqual(expected);
|
275
|
-
});
|
276
|
-
});
|