[AAE-6660] FE - [ADF] Linked dropdown still contains old options when the rest api does not return results (#7454)

* [AAE-6660] FE - [ADF] Linked dropdown still contains old options when the rest api does not return results

* * Added unit tests to the recent changes done on dropdown.

* * Improved error message

* My empty commit to kick start travis

* * Fixed lint errors

* * Fixed css lint error

* * Fixed failing unit test
This commit is contained in:
siva kumar
2022-01-24 14:47:44 +05:30
committed by GitHub
parent d605efaacb
commit 4ffa338585
6 changed files with 109 additions and 7 deletions

View File

@@ -29,4 +29,6 @@
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<error-widget class="adf-dropdown-failed-message" *ngIf="isRestApiFailed"
required="{{ 'FORM.FIELD.REST_API_FAILED' | translate: { hostname: restApiHostName } }}"></error-widget>
</div>

View File

@@ -19,5 +19,9 @@
&-dropdown-required-message .adf-error-text-container {
margin-top: 1px !important;
}
&-dropdown-failed-message .adf-error-text-container {
margin-top: 1px !important;
}
}
}

View File

@@ -17,7 +17,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
import { of, throwError } from 'rxjs';
import { DropdownCloudWidgetComponent } from './dropdown-cloud.widget';
import { FormFieldModel, FormModel, FormService, setupTestBed } from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service';
@@ -27,7 +27,8 @@ import {
fakeOptionList,
filterOptionList,
mockConditionalEntries,
mockRestDropdownOptions
mockRestDropdownOptions,
mockSecondRestDropdownOptions
} from '../../../mocks/dropdown.mock';
import { OverlayContainer } from '@angular/cdk/overlay';
@@ -78,7 +79,7 @@ describe('DropdownCloudWidgetComponent', () => {
name: 'date-name',
type: 'dropdown',
readOnly: false,
restUrl: 'fake-rest-url'
restUrl: 'https://fake-rest-url'
});
widget.field.emptyOption = { id: 'empty', name: 'Choose one...' };
widget.field.isVisible = true;
@@ -134,7 +135,7 @@ describe('DropdownCloudWidgetComponent', () => {
it('should load data from restUrl and populate options', async () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of(fakeOptionList));
widget.field.restUrl = 'fake-rest-url';
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.restIdProperty = 'name';
@@ -159,8 +160,30 @@ describe('DropdownCloudWidgetComponent', () => {
expect(optThree.nativeElement.innerText).toEqual('option_3');
});
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'));
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.restIdProperty = 'name';
widget.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
const dropdown = fixture.debugElement.query(By.css('mat-select'));
dropdown.nativeElement.click();
fixture.detectChanges();
await fixture.whenStable();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(jsonDataSpy).toHaveBeenCalled();
expect(widget.isRestApiFailed).toBe(true);
expect(widget.field.options.length).toEqual(0);
expect(failedErrorMsgElement.nativeElement.innerText.trim()).toBe('FORM.FIELD.REST_API_FAILED');
});
it('should preselect dropdown widget value when Json (rest call) passed', async () => {
widget.field.restUrl = 'fake-rest-url';
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.value = {
id: 'opt1',
@@ -188,7 +211,7 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should preselect dropdown widget value when String (defined value) passed ', async () => {
widget.field.restUrl = 'fake-rest-url';
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.value = 'opt1';
@@ -367,6 +390,44 @@ describe('DropdownCloudWidgetComponent', () => {
expect(optTwo.context.value).toBe('MA');
expect(optTwo.context.viewValue).toBe('MANCHESTER');
});
it('should reset previous child options if the rest url failed for a linked dropdown', async () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of(mockRestDropdownOptions));
const mockParentDropdown = { id: 'parentDropdown', value: 'mock-value', validate: () => true };
spyOn(widget.field.form, 'getFormFields').and.returnValue([mockParentDropdown]);
function selectParentOption(parentOptionName: string) {
parentDropdown.value = parentOptionName;
widget.selectionChangedForField(parentDropdown);
fixture.detectChanges();
}
selectParentOption('UK');
await openSelect('child-dropdown-id');
const failedErrorMsgElement1 = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(widget.isRestApiFailed).toBe(false);
expect(widget.field.options.length).toBe(2);
expect(failedErrorMsgElement1).toBeNull();
jsonDataSpy.and.returnValue(throwError('Failed to fetch options'));
selectParentOption('GR');
await openSelect('child-dropdown-id');
const failedErrorMsgElement2 = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(widget.isRestApiFailed).toBe(true);
expect(widget.field.options.length).toBe(0);
expect(failedErrorMsgElement2.nativeElement.innerText.trim()).toBe('FORM.FIELD.REST_API_FAILED');
jsonDataSpy.and.returnValue(of(mockSecondRestDropdownOptions));
selectParentOption('IT');
await openSelect('child-dropdown-id');
const failedErrorMsgElement3 = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(widget.isRestApiFailed).toBe(false);
expect(widget.field.options.length).toBe(2);
expect(failedErrorMsgElement3).toBeNull();
});
});
describe('Manual options', () => {

View File

@@ -59,6 +59,8 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
typeId = 'DropdownCloudWidgetComponent';
HIDE_FILTER_LIMIT = 5;
showInputFilter = false;
isRestApiFailed = false;
restApiHostName: string;
list$: Observable<FormFieldOption[]>;
filter$ = new BehaviorSubject<string>('');
@@ -93,14 +95,19 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private persistFieldOptionsFromRestApi() {
if (this.isValidRestType()) {
this.resetRestApiErrorMessage();
const bodyParam = this.buildBodyParam();
this.formCloudService.getRestWidgetData(this.field.form.id, this.field.id, bodyParam)
.pipe(takeUntil(this.onDestroy$))
.subscribe((result: FormFieldOption[]) => {
this.resetRestApiErrorMessage();
this.field.options = result;
this.updateOptions();
this.field.updateForm();
}, (err) => this.handleError(err));
}, (err) => {
this.resetRestApiOptions();
this.handleError(err);
});
}
}
@@ -129,6 +136,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
if (this.isValidValue(value)) {
this.isValidRestType() ? this.persistFieldOptionsFromRestApi() : this.persistFieldOptionsFromManualList(value);
} else if (this.isDefaultValue(value)) {
this.resetRestApiErrorMessage();
this.addDefaultOption();
}
}
@@ -253,4 +261,25 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
takeUntil(this.onDestroy$)
);
}
resetRestApiErrorMessage() {
this.isRestApiFailed = false;
this.restApiHostName = '';
}
resetRestApiOptions() {
this.field.options = [];
this.isRestApiFailed = true;
this.restApiHostName = this.getRestUrlHostName();
this.updateOptions();
this.field.updateForm();
}
private getRestUrlHostName(): string {
try {
return new URL(this.field?.restUrl).hostname;
} catch {
return this.field?.restUrl;
}
}
}

View File

@@ -84,6 +84,11 @@ export const mockRestDropdownOptions: FormFieldOption[] = [
{ id: 'MA', name: 'MANCHESTER' }
];
export const mockSecondRestDropdownOptions: FormFieldOption[] = [
{ id: 'MI', name: 'MILAN' },
{ id: 'RM', name: 'ROME' }
];
export const fakeOptionList: FormFieldOption[] = [
{ id: 'opt_1', name: 'option_1' },
{ id: 'opt_2', name: 'option_2' },