[MNT-22348] - Fixed visibility when complex cases are appling (#7176)

* [MNT-22348] - Fixed visibility when complex cases are appling

* [MNT-22348] - Fixed lint errrors

* [MNT-22461] Unit test for visibility condition behaviour for checkxox expression is added

* fixed unit test for visibility condition

* [MNT-22348] - Fixed wrong form definition

* [MNT-22348] - Fixed wrong quote

* [MNT-22348] - Fixed wrong form definition

* [MNT-22348] - fixed form definition

Co-authored-by: Ketevani Kvirikashvili <qqetikv@gmail.com>
This commit is contained in:
Vito
2021-07-28 11:30:40 +01:00
committed by GitHub
parent deb925679c
commit bd1b879e44
5 changed files with 1243 additions and 588 deletions

View File

@@ -61,54 +61,6 @@ describe('WidgetVisibilityCloudService', () => {
jasmine.Ajax.uninstall();
});
describe('should be able to evaluate logic operations', () => {
it('using AND and return true', () => {
booleanResult = service.evaluateLogicalOperation('and', true, true);
expect(booleanResult).toBeTruthy();
});
it('using AND and return false', () => {
booleanResult = service.evaluateLogicalOperation('and', true, false);
expect(booleanResult).toBeFalsy();
});
it('using OR and return true', () => {
booleanResult = service.evaluateLogicalOperation('or', true, false);
expect(booleanResult).toBeTruthy();
});
it('using OR and return false', () => {
booleanResult = service.evaluateLogicalOperation('or', false, false);
expect(booleanResult).toBeFalsy();
});
it('using AND NOT and return true', () => {
booleanResult = service.evaluateLogicalOperation('and-not', true, false);
expect(booleanResult).toBeTruthy();
});
it('using AND NOT and return false', () => {
booleanResult = service.evaluateLogicalOperation('and-not', false, false);
expect(booleanResult).toBeFalsy();
});
it('using OR NOT and return true', () => {
booleanResult = service.evaluateLogicalOperation('or-not', true, true);
expect(booleanResult).toBeTruthy();
});
it('using OR NOT and return false', () => {
booleanResult = service.evaluateLogicalOperation('or-not', false, true);
expect(booleanResult).toBeFalsy();
});
it('should fail with invalid operation', () => {
booleanResult = service.evaluateLogicalOperation(undefined, false, true);
expect(booleanResult).toBeUndefined();
});
});
describe('should be able to evaluate next condition operations', () => {
it('using == and return true', () => {

View File

@@ -32,7 +32,9 @@ import {
fakeFormJson, formTest,
formValues, complexVisibilityJsonVisible,
complexVisibilityJsonNotVisible, tabVisibilityJsonMock,
tabInvalidFormVisibility
tabInvalidFormVisibility,
fakeFormChainedVisibilityJson,
fakeFormCheckBoxVisibilityJson
} from 'core/mock/form/widget-visibility.service.mock';
import { CoreTestingModule } from '../../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -63,50 +65,6 @@ describe('WidgetVisibilityService', () => {
describe('should be able to evaluate logic operations', () => {
it('using AND and return true', () => {
booleanResult = service.evaluateLogicalOperation('and', true, true);
expect(booleanResult).toBeTruthy();
});
it('using AND and return false', () => {
booleanResult = service.evaluateLogicalOperation('and', true, false);
expect(booleanResult).toBeFalsy();
});
it('using OR and return true', () => {
booleanResult = service.evaluateLogicalOperation('or', true, false);
expect(booleanResult).toBeTruthy();
});
it('using OR and return false', () => {
booleanResult = service.evaluateLogicalOperation('or', false, false);
expect(booleanResult).toBeFalsy();
});
it('using AND NOT and return true', () => {
booleanResult = service.evaluateLogicalOperation('and-not', true, false);
expect(booleanResult).toBeTruthy();
});
it('using AND NOT and return false', () => {
booleanResult = service.evaluateLogicalOperation('and-not', false, false);
expect(booleanResult).toBeFalsy();
});
it('using OR NOT and return true', () => {
booleanResult = service.evaluateLogicalOperation('or-not', true, true);
expect(booleanResult).toBeTruthy();
});
it('using OR NOT and return false', () => {
booleanResult = service.evaluateLogicalOperation('or-not', false, true);
expect(booleanResult).toBeFalsy();
});
it('should fail with invalid operation', () => {
booleanResult = service.evaluateLogicalOperation(undefined, false, true);
expect(booleanResult).toBeUndefined();
});
});
describe('should be able to evaluate next condition operations', () => {
@@ -1122,4 +1080,65 @@ describe('WidgetVisibilityService', () => {
expect(invalidTabVisibilityJsonModel.isValid).toBeTruthy();
});
});
describe('Visibility calculation in complex forms', () => {
const fakeFormWithVariables = new FormModel(fakeFormChainedVisibilityJson);
it('Should be able to validate correctly the visibility for the text field for complex expressions', () => {
const instalmentField = fakeFormWithVariables.getFieldById('installments');
const scheduleField = fakeFormWithVariables.getFieldById('schedule');
instalmentField.value = '6';
scheduleField.value = scheduleField.options[1].id;
service.refreshVisibility(fakeFormWithVariables);
let textField = fakeFormWithVariables.getFieldById('showtext');
expect(textField.isVisible).toBe(true);
instalmentField.value = '5';
scheduleField.value = scheduleField.options[1].id;
service.refreshVisibility(fakeFormWithVariables);
textField = fakeFormWithVariables.getFieldById('showtext');
expect(textField.isVisible).toBe(false);
});
});
describe('Visibility calculation in checkbox forms', () => {
const fakeFormWithValues = new FormModel(fakeFormCheckBoxVisibilityJson);
it('Should be able to validate correctly the visibility for the checkbox expression', () => {
const fieldA = fakeFormWithValues.getFieldById('a');
const fieldB = fakeFormWithValues.getFieldById('b');
const fieldC = fakeFormWithValues.getFieldById('c');
const fieldD = fakeFormWithValues.getFieldById('d');
fieldA.value = true;
fieldB.value = true;
fieldC.value = false;
fieldD.value = false;
service.refreshVisibility(fakeFormWithValues);
const textField = fakeFormWithValues.getFieldById('a_b_c_d');
expect(textField.isVisible).toBe(true);
fieldB.value = false;
service.refreshVisibility(fakeFormWithValues);
expect(textField.isVisible).toBe(false);
fieldA.value = false;
fieldC.value = true;
fieldD.value = true;
service.refreshVisibility(fakeFormWithValues);
expect(textField.isVisible).toBe(true);
});
});
});

View File

@@ -84,28 +84,38 @@ export class WidgetVisibilityService {
const rightValue = this.getRightValue(form, visibilityObj);
const actualResult = this.evaluateCondition(leftValue, rightValue, visibilityObj.operator);
if (this.isValidOperator(visibilityObj.nextConditionOperator)) {
accumulator.push({ value: actualResult, operator: visibilityObj.nextConditionOperator });
}
accumulator.push({ value: actualResult, operator: visibilityObj.nextConditionOperator });
if (this.isValidCondition(visibilityObj.nextCondition)) {
result = this.isFieldVisible(form, visibilityObj.nextCondition, accumulator);
} else if (accumulator[0] !== undefined) {
result = accumulator[0].value;
for (let i = 1; i < accumulator.length; i++) {
if (accumulator[i] !== undefined) {
result = this.evaluateLogicalOperation(
accumulator[i - 1].operator,
result,
accumulator[i].value
);
}
}
result = Function('"use strict";return (' +
accumulator.map((expression) => this.transformToLiteralExpression(expression)).join('') +
')')();
} else {
result = actualResult;
}
return !!result;
}
private transformToLiteralExpression(currentExpression: any): string {
const currentTransformedValue = !!currentExpression.value ? 'true' : 'false';
return currentTransformedValue.concat(this.transformToLiteralOperator(currentExpression.operator));
}
private transformToLiteralOperator(currentOperator): string {
switch (currentOperator) {
case 'and':
return '&&';
case 'or' :
return '||';
case 'and-not':
return '&& !';
case 'or-not':
return '|| !';
default:
return '';
}
}
getLeftValue(form: FormModel, visibilityObj: WidgetVisibilityModel): string {
@@ -280,22 +290,6 @@ export class WidgetVisibilityService {
return undefined;
}
evaluateLogicalOperation(logicOp: string, previousValue: any, newValue: any): boolean | undefined {
switch (logicOp) {
case 'and':
return previousValue && newValue;
case 'or' :
return previousValue || newValue;
case 'and-not':
return previousValue && !newValue;
case 'or-not':
return previousValue || !newValue;
default:
this.logService.error(`Invalid operator: ${logicOp}`);
return undefined;
}
}
evaluateCondition(leftValue: any, rightValue: any, operator: string): boolean | undefined {
switch (operator) {
case '==':
@@ -340,10 +334,6 @@ export class WidgetVisibilityService {
return res || {};
}
private isValidOperator(operator: string): boolean {
return operator !== undefined;
}
private isValidCondition(condition: WidgetVisibilityModel): boolean {
return !!(condition && condition.operator);
}