AAE-23116 Dropdown should not display errors / call apis when it's in readOnly state [without refactor] (#9800)

* AAE-23116 Add tests for dropdown widget

* AAE-23116 Update form-field.model

* AAE-23116 Final

* AAE-23116 Restore formatting

* AAE-23116 Align with comments

* AAE-23116 Update

* AAE-23116 Fix process-services-cloud unit tests

* AAE-23116 Fix process services unit tests

* AAE-23116 Fix for core unit tests
This commit is contained in:
Wiktor Danielewski
2024-06-21 08:50:55 +02:00
committed by GitHub
parent 328d233b05
commit 4d2c489508
7 changed files with 395 additions and 344 deletions

View File

@@ -64,11 +64,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('Simple Dropdown', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: false,
restUrl: 'https://fake-rest-url',
options: [{ id: 'empty', name: 'Choose one...' }]
});
@@ -120,6 +119,18 @@ describe('DropdownCloudWidgetComponent', () => {
expect(await allOptions[2].getText()).toEqual('option_3');
});
it('should NOT load data from restUrl when field is readonly', () => {
spyOn(formCloudService, 'getRestWidgetData');
widget.field.readOnly = true;
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.restIdProperty = 'name';
widget.ngOnInit();
expect(formCloudService.getRestWidgetData).not.toHaveBeenCalled();
});
it('should show error message if the restUrl failed to fetch options', async () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(throwError('Failed to fetch options'));
const errorIcon: string = 'error_outline';
@@ -315,15 +326,30 @@ describe('DropdownCloudWidgetComponent', () => {
const requiredErrorElement = fixture.debugElement.query(By.css('.adf-dropdown-required-message .adf-error-text'));
expect(requiredErrorElement.nativeElement.innerText).toEqual('FORM.FIELD.REQUIRED');
});
it('should NOT display a required error when dropdown is readonly', async () => {
widget.field.readOnly = true;
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-invalid')).toBeFalsy();
const dropdownSelect = element.querySelector('.adf-select');
dropdownSelect.dispatchEvent(new Event('blur'));
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-invalid')).toBeFalsy();
});
});
describe('filter', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'option list',
type: 'dropdown',
readOnly: false,
options: filterOptionList
});
widget.ngOnInit();
@@ -370,11 +396,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('multiple selection', () => {
it('should show preselected option', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
options: fakeOptionList,
selectionType: 'multiple',
value: [
@@ -389,11 +414,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should support multiple options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
selectionType: 'multiple',
options: fakeOptionList
});
@@ -408,11 +432,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should show preselected option for rest options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType: 'rest',
selectionType: 'multiple',
@@ -448,11 +471,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should support multiple options for rest options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType: 'rest',
selectionType: 'multiple'
@@ -498,11 +520,10 @@ describe('DropdownCloudWidgetComponent', () => {
validate: () => true
});
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'rest',
restUrl: 'myFakeDomain.com/cities?country=${parentDropdown}',
rule: {
@@ -605,11 +626,10 @@ describe('DropdownCloudWidgetComponent', () => {
const parentDropdown = new FormFieldModel(new FormModel(), { id: 'parentDropdown', type: 'dropdown' });
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'manual',
rule: {
ruleOn: 'parentDropdown',
@@ -694,11 +714,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => {
it('should load the selection of a manual type linked dropdown', () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'manual',
rule: {
ruleOn: 'parentDropdown',
@@ -718,11 +737,10 @@ describe('DropdownCloudWidgetComponent', () => {
it('should load the selection of a rest type linked dropdown', () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of(mockRestDropdownOptions));
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
restUrl: 'mock-url.com/country=${country}',
optionType: 'rest',
rule: {
@@ -744,11 +762,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false, leftLabels: true }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -763,11 +780,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should not have left labels classes on leftLabels false', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: false }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false, leftLabels: false }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -782,11 +798,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should not have left labels classes on leftLabels not present', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -813,11 +828,10 @@ describe('DropdownCloudWidgetComponent', () => {
processVariables?: TaskVariableCloud[],
variables?: TaskVariableCloud[]
) =>
new FormFieldModel(new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false', processVariables, variables }), {
id: 'variable-dropdown-id',
name: 'variable-options-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'variable',
variableConfig: {
variableName,
@@ -961,5 +975,20 @@ describe('DropdownCloudWidgetComponent', () => {
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(failedErrorMsgElement).toBeNull();
});
it('should NOT display errors if field is readonly', () => {
widget.field = getVariableDropdownWidget(
'variables.wrong-variable-id',
'response.wrongPath.players',
'wrongId',
'wrongFullName',
mockProcessVariablesWithJson
);
widget.field.readOnly = true;
fixture.detectChanges();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(failedErrorMsgElement).toBeNull();
});
});
});

View File

@@ -84,7 +84,9 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private checkFieldOptionsSource(): void {
switch (true) {
case this.field.restUrl && !this.isLinkedWidget():
case this.isReadOnly():
break;
case this.hasRestUrl() && !this.isLinkedWidget():
this.persistFieldOptionsFromRestApi();
break;
@@ -377,7 +379,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private isValidRestType(): boolean {
return this.field.optionType === 'rest' && !!this.field.restUrl;
return this.field.optionType === 'rest' && this.hasRestUrl();
}
private setPreviewState(): void {
@@ -390,6 +392,14 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
}
private isReadOnly(): boolean {
return this.field.readOnly;
}
private hasRestUrl(): boolean {
return !!this.field.restUrl;
}
isReadOnlyType(): boolean {
return this.field.type === 'readonly';
}
@@ -400,6 +410,10 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
updateOptions(): void {
if (this.isReadOnly()) {
this.list$ = of(this.field.options);
}
this.showInputFilter = this.field.options.length > this.appConfig.get<number>('form.dropDownFilterLimit', HIDE_FILTER_LIMIT);
this.list$ = combineLatest([of(this.field.options), this.filter$]).pipe(
map(([items, search]) => {