diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html index a38c6f0383..27fe1892fb 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.html @@ -30,7 +30,7 @@ {{field.value}} -
+
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts index 170e36a45a..c8809b5a60 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.spec.ts @@ -37,6 +37,7 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatSelectHarness } from '@angular/material/select/testing'; import { MatFormFieldHarness } from '@angular/material/form-field/testing'; +import { DebugElement } from '@angular/core'; describe('DropdownCloudWidgetComponent', () => { let formService: FormService; @@ -118,35 +119,79 @@ describe('DropdownCloudWidgetComponent', () => { expect(await allOptions[2].getText()).toEqual('option_3'); }); - it('should NOT load data from restUrl when field is readonly', () => { + it('should NOT load data from restUrl when form is readonly', () => { spyOn(formCloudService, 'getRestWidgetData'); - widget.field.readOnly = true; + widget.field.readOnly = false; widget.field.restUrl = 'https://fake-rest-url'; widget.field.optionType = 'rest'; - widget.field.restIdProperty = 'name'; + widget.field.form.readOnly = true; 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')); + describe('should load data from restUrl when form is NOT readonly', () => { + beforeEach(() => { + spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([])); + + widget.field.restUrl = 'https://fake-rest-url'; + widget.field.optionType = 'rest'; + widget.field.restIdProperty = 'name'; + widget.field.form.readOnly = false; + }); + + it('when widget is NOT readonly', () => { + widget.field.readOnly = false; + widget.ngOnInit(); + + expect(formCloudService.getRestWidgetData).toHaveBeenCalled(); + }); + + it('when widget is readonly', () => { + widget.field.readOnly = true; + widget.ngOnInit(); + + expect(formCloudService.getRestWidgetData).toHaveBeenCalled(); + }); + }); + + describe('when failed on loading options from restUrl', () => { + let getRestWidgetDataSpy: jasmine.Spy; + const getErrorMessageElement = (): DebugElement => fixture.debugElement.query(By.css('.adf-dropdown-failed-message')); const errorIcon: string = 'error_outline'; - widget.field.restUrl = 'https://fake-rest-url'; - widget.field.optionType = 'rest'; - widget.field.restIdProperty = 'name'; - widget.ngOnInit(); + beforeEach(() => { + getRestWidgetDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(throwError('Failed to fetch options')); + widget.field.restUrl = 'https://fake-rest-url'; + widget.field.optionType = 'rest'; + }); - const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); - await dropdown.open(); + it('should show error message when widget is NOT readonly', () => { + widget.field.readOnly = false; - 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.textContent.trim()).toBe(errorIcon + 'FORM.FIELD.REST_API_FAILED'); + widget.ngOnInit(); + fixture.detectChanges(); + + const errorMessageElement = getErrorMessageElement(); + expect(getRestWidgetDataSpy).toHaveBeenCalled(); + expect(widget.isRestApiFailed).toBe(true); + expect(widget.field.options.length).toEqual(0); + expect(errorMessageElement.nativeElement.textContent.trim()).toBe(errorIcon + 'FORM.FIELD.REST_API_FAILED'); + }); + + it('should NOT show error message when widget is readonly', async () => { + widget.field.readOnly = true; + + widget.ngOnInit(); + fixture.detectChanges(); + + const errorMessageElement = getErrorMessageElement(); + expect(getRestWidgetDataSpy).toHaveBeenCalled(); + expect(widget.isRestApiFailed).toBe(true); + expect(widget.field.options.length).toEqual(0); + expect(errorMessageElement).toBe(null); + }); }); it('should preselect dropdown widget value when Json (rest call) passed', async () => { diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts index 3b852b85ad..ad027d2716 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/dropdown/dropdown-cloud.widget.ts @@ -84,7 +84,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI private checkFieldOptionsSource(): void { switch (true) { - case this.isReadOnly(): + case this.isReadOnlyForm(): break; case this.hasRestUrl() && !this.isLinkedWidget(): this.persistFieldOptionsFromRestApi(); @@ -392,7 +392,11 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI } } - private isReadOnly(): boolean { + private isReadOnlyForm(): boolean { + return !!this.field?.form?.readOnly; + } + + get isReadOnlyField(): boolean { return this.field.readOnly; } @@ -410,7 +414,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI } updateOptions(): void { - if (this.isReadOnly()) { + if (this.isReadOnlyForm()) { this.list$ = of(this.field.options); } diff --git a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.html b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.html index c77a1db3e9..42d22640f0 100644 --- a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.html +++ b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.html @@ -15,7 +15,9 @@ {{field.value}} - - + + +
diff --git a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.spec.ts b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.spec.ts index 08047fa2cf..e7ae7ee817 100644 --- a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.spec.ts +++ b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.spec.ts @@ -17,7 +17,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Observable, of } from 'rxjs'; -import { WidgetVisibilityService, FormFieldOption, FormFieldModel, FormModel, FormFieldTypes, CoreTestingModule } from '@alfresco/adf-core'; +import { + WidgetVisibilityService, + FormFieldOption, + FormFieldModel, + FormModel, + FormFieldTypes, + CoreTestingModule, + ErrorMessageModel +} from '@alfresco/adf-core'; import { DropdownWidgetComponent } from './dropdown.widget'; import { TaskFormService } from '../../services/task-form.service'; import { ProcessDefinitionService } from '../../services/process-definition.service'; @@ -66,27 +74,40 @@ describe('DropdownWidgetComponent', () => { expect(taskFormService.getRestFieldValues).not.toHaveBeenCalled(); }); - it('should request field values from service', () => { + describe('requesting field options', () => { + let getRestFieldValuesSpy: jasmine.Spy; const taskId = ''; const fieldId = ''; - const form = new FormModel({ - taskId + beforeEach(() => { + getRestFieldValuesSpy = spyOn(taskFormService, 'getRestFieldValues').and.returnValue(of([])); + + widget.field = new FormFieldModel(new FormModel({ taskId }), { id: fieldId, restUrl: '' }); }); - widget.field = new FormFieldModel(form, { - id: fieldId, - restUrl: '' + it('should request options from service when form is NOT readonly', () => { + widget.field.form.readOnly = false; + widget.ngOnInit(); + + expect(getRestFieldValuesSpy).toHaveBeenCalledWith(taskId, fieldId); }); - spyOn(taskFormService, 'getRestFieldValues').and.returnValue( - new Observable((observer) => { - observer.next(null); - observer.complete(); - }) - ); + it('should NOT request options from service when form is readonly', () => { + widget.field.form.readOnly = true; + widget.ngOnInit(); + + expect(getRestFieldValuesSpy).not.toHaveBeenCalled(); + }); + }); + + it('should NOT display any error when widget is readonly', () => { + widget.field = new FormFieldModel(new FormModel({}, undefined, false), { readOnly: true }); + widget.field.validationSummary = { message: 'Some error occurred' } as ErrorMessageModel; + widget.ngOnInit(); - expect(taskFormService.getRestFieldValues).toHaveBeenCalledWith(taskId, fieldId); + fixture.detectChanges(); + + expect(element.querySelector('.adf-dropdown-required-message')).toBeNull(); }); it('should preserve empty option when loading fields', () => { diff --git a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.ts b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.ts index 47d578dbbb..b3886ee4a4 100644 --- a/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.ts +++ b/lib/process-services/src/lib/form/widgets/dropdown/dropdown.widget.ts @@ -52,7 +52,7 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit { } ngOnInit() { - if (this.field?.restUrl) { + if (this.field?.restUrl && !this.isReadOnlyForm()) { if (this.field.form.taskId) { this.getValuesByTaskId(); } else { @@ -102,4 +102,12 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit { showRequiredMessage(): boolean { return (this.isInvalidFieldRequired() || this.field.value === 'empty') && this.isTouched(); } + + get isReadOnlyField(): boolean { + return this.field.readOnly; + } + + private isReadOnlyForm(): boolean { + return !!this.field?.form?.readOnly; + } }