AAE-21392 Fix dropdown form widget style

This commit is contained in:
Diogo Bastos
2024-04-16 14:21:11 +01:00
parent ed6526a800
commit 2d85c716e0
2 changed files with 131 additions and 125 deletions
@@ -1,15 +1,10 @@
<div class="adf-dropdown-widget {{field.className}}" <div class="adf-dropdown-widget {{field.className}}"
[class.adf-invalid]="(!field.isValid && isTouched()) || isRestApiFailed" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels"> [class.adf-invalid]="(!field.isValid && isTouched()) || isRestApiFailed" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div class="adf-dropdown-widget-top-labels"> <div>
<mat-form-field>
<label class="adf-label" [attr.for]="field.id" [class.adf-left-label]="field.leftLabels">{{field.name | translate }}<span class="adf-asterisk" <label class="adf-label" [attr.for]="field.id" [class.adf-left-label]="field.leftLabels">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span> *ngIf="isRequired()">*</span>
</label> </label>
</div>
<div>
<mat-form-field>
<mat-label *ngIf="getDefaultOption(list$ | async) as defaultOption">
{{ defaultOption.name }}
</mat-label>
<mat-select class="adf-select" <mat-select class="adf-select"
[id]="field.id" [id]="field.id"
[(ngModel)]="field.value" [(ngModel)]="field.value"
@@ -22,6 +17,7 @@
(blur)="markAsTouched()" (blur)="markAsTouched()"
matTooltipPosition="above" matTooltipPosition="above"
matTooltipShowDelay="1000" matTooltipShowDelay="1000"
[placeholder]="getDefaultOption(list$ | async)?.name"
[multiple]="field.hasMultipleValues"> [multiple]="field.hasMultipleValues">
<adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)"></adf-select-filter-input> <adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)"></adf-select-filter-input>
@@ -19,14 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { DropdownCloudWidgetComponent } from './dropdown-cloud.widget'; import { DropdownCloudWidgetComponent } from './dropdown-cloud.widget';
import { import { FormFieldModel, FormModel, FormService, FormFieldEvent, FormFieldTypes, LogService } from '@alfresco/adf-core';
FormFieldModel,
FormModel,
FormService,
FormFieldEvent,
FormFieldTypes,
LogService
} from '@alfresco/adf-core';
import { FormCloudService } from '../../../services/form-cloud.service'; import { FormCloudService } from '../../../services/form-cloud.service';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@@ -45,11 +38,9 @@ import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
import { HarnessLoader } from '@angular/cdk/testing'; import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing'; import { MatSelectHarness } from '@angular/material/select/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing'; import { MatTooltipHarness } from '@angular/material/tooltip/testing';
describe('DropdownCloudWidgetComponent', () => { describe('DropdownCloudWidgetComponent', () => {
let formService: FormService; let formService: FormService;
let widget: DropdownCloudWidgetComponent; let widget: DropdownCloudWidgetComponent;
let formCloudService: FormCloudService; let formCloudService: FormCloudService;
@@ -60,10 +51,7 @@ describe('DropdownCloudWidgetComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
TranslateModule.forRoot(),
ProcessServiceCloudTestingModule
]
}); });
fixture = TestBed.createComponent(DropdownCloudWidgetComponent); fixture = TestBed.createComponent(DropdownCloudWidgetComponent);
widget = fixture.componentInstance; widget = fixture.componentInstance;
@@ -78,7 +66,6 @@ describe('DropdownCloudWidgetComponent', () => {
afterEach(() => fixture.destroy()); afterEach(() => fixture.destroy());
describe('Simple Dropdown', () => { describe('Simple Dropdown', () => {
beforeEach(() => { beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), { widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'dropdown-id', id: 'dropdown-id',
@@ -163,7 +150,8 @@ describe('DropdownCloudWidgetComponent', () => {
name: 'default1_value' name: 'default1_value'
}; };
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([ spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{ {
id: 'opt1', id: 'opt1',
name: 'default1_value' name: 'default1_value'
@@ -172,14 +160,15 @@ describe('DropdownCloudWidgetComponent', () => {
id: 2, id: 2,
name: 'default2_value' name: 'default2_value'
} }
] as any)); ] as any)
);
widget.ngOnInit(); widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open(); await dropdown.open();
expect((await (await dropdown.getOptions())[0].getText())).toEqual('default1_value'); expect(await (await dropdown.getOptions())[0].getText()).toEqual('default1_value');
}); });
it('should preselect dropdown widget value when String (defined value) passed ', async () => { it('should preselect dropdown widget value when String (defined value) passed ', async () => {
@@ -187,7 +176,8 @@ describe('DropdownCloudWidgetComponent', () => {
widget.field.optionType = 'rest'; widget.field.optionType = 'rest';
widget.field.value = 'opt1'; widget.field.value = 'opt1';
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([ spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{ {
id: 'opt1', id: 'opt1',
name: 'default1_value' name: 'default1_value'
@@ -196,21 +186,19 @@ describe('DropdownCloudWidgetComponent', () => {
id: 2, id: 2,
name: 'default2_value' name: 'default2_value'
} }
] as any)); ] as any)
);
widget.ngOnInit(); widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open(); await dropdown.open();
expect((await (await dropdown.getOptions())[0].getText())).toEqual('default1_value'); expect(await (await dropdown.getOptions())[0].getText()).toEqual('default1_value');
expect(widget.field.form.values['dropdown-id']).toEqual({ id: 'opt1', name: 'default1_value' }); expect(widget.field.form.values['dropdown-id']).toEqual({ id: 'opt1', name: 'default1_value' });
}); });
it('should not display required error for a non required dropdown when selecting the none option', async () => { it('should not display required error for a non required dropdown when selecting the none option', async () => {
widget.field.options = [ widget.field.options = [{ id: 'empty', name: 'Choose empty' }, ...fakeOptionList];
{ id: 'empty', name: 'Choose empty' },
...fakeOptionList
];
widget.ngOnInit(); widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -226,10 +214,7 @@ describe('DropdownCloudWidgetComponent', () => {
it('should not display required error when selecting a valid option for a required dropdown', async () => { it('should not display required error when selecting a valid option for a required dropdown', async () => {
widget.field.required = true; widget.field.required = true;
widget.field.options = [ widget.field.options = [{ id: 'empty', name: 'Choose empty' }, ...fakeOptionList];
{ id: 'empty', name: 'Choose empty' },
...fakeOptionList
];
widget.ngOnInit(); widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -243,10 +228,7 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should not have a value when switching from an available option to the None option', async () => { it('should not have a value when switching from an available option to the None option', async () => {
widget.field.options = [ widget.field.options = [{ id: 'empty', name: 'This is a mock none option' }, ...fakeOptionList];
{ id: 'empty', name: 'This is a mock none option' },
...fakeOptionList
];
widget.ngOnInit(); widget.ngOnInit();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -260,17 +242,12 @@ describe('DropdownCloudWidgetComponent', () => {
await dropdown.open(); await dropdown.open();
await dropdown.clickOptions({ selector: '[id="empty"]' }); await dropdown.clickOptions({ selector: '[id="empty"]' });
const formField = await loader.getHarness(MatFormFieldHarness); expect(await dropdown.getValueText()).toEqual('This is a mock none option');
const dropdownLabel = await formField.getLabel();
expect(dropdownLabel).toEqual('This is a mock none option');
expect(widget.fieldValue).toEqual(undefined); expect(widget.fieldValue).toEqual(undefined);
expect(await dropdown.getValueText()).toEqual('');
}); });
}); });
describe('when tooltip is set', () => { describe('when tooltip is set', () => {
beforeEach(() => { beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), { widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DROPDOWN, type: FormFieldTypes.DROPDOWN,
@@ -303,9 +280,8 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('when is required', () => { describe('when is required', () => {
beforeEach(() => { beforeEach(() => {
widget.field = new FormFieldModel( new FormModel({ taskId: '<id>' }), { widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DROPDOWN, type: FormFieldTypes.DROPDOWN,
required: true required: true
}); });
@@ -341,7 +317,6 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('filter', () => { describe('filter', () => {
beforeEach(() => { beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), { widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
id: 'dropdown-id', id: 'dropdown-id',
@@ -393,7 +368,6 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('multiple selection', () => { describe('multiple selection', () => {
it('should show preselected option', async () => { 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' }), {
id: 'dropdown-id', id: 'dropdown-id',
@@ -439,14 +413,15 @@ describe('DropdownCloudWidgetComponent', () => {
type: 'dropdown', type: 'dropdown',
readOnly: 'false', readOnly: 'false',
restUrl: 'https://fake-rest-url', restUrl: 'https://fake-rest-url',
optionType : 'rest', optionType: 'rest',
selectionType: 'multiple', selectionType: 'multiple',
value: [ value: [
{ id: 'opt_3', name: 'option_3' }, { id: 'opt_3', name: 'option_3' },
{ id: 'opt_4', name: 'option_4' } { id: 'opt_4', name: 'option_4' }
] ]
}); });
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([ spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{ {
id: 'opt_1', id: 'opt_1',
name: 'option_1' name: 'option_1'
@@ -463,7 +438,8 @@ describe('DropdownCloudWidgetComponent', () => {
id: 'opt_4', id: 'opt_4',
name: 'option_4' name: 'option_4'
} }
] as any)); ] as any)
);
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
@@ -477,11 +453,12 @@ describe('DropdownCloudWidgetComponent', () => {
type: 'dropdown', type: 'dropdown',
readOnly: 'false', readOnly: 'false',
restUrl: 'https://fake-rest-url', restUrl: 'https://fake-rest-url',
optionType : 'rest', optionType: 'rest',
selectionType: 'multiple' selectionType: 'multiple'
}); });
spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of([ spyOn(formCloudService, 'getRestWidgetData').and.returnValue(
of([
{ {
id: 'opt_1', id: 'opt_1',
name: 'option_1' name: 'option_1'
@@ -498,7 +475,8 @@ describe('DropdownCloudWidgetComponent', () => {
id: 'opt_4', id: 'opt_4',
name: 'option_4' name: 'option_4'
} }
] as any)); ] as any)
);
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.clickOptions({ selector: '[id="opt_2"]' }); await dropdown.clickOptions({ selector: '[id="opt_2"]' });
@@ -512,9 +490,7 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('Linked Dropdown', () => { describe('Linked Dropdown', () => {
describe('Rest URL options', () => { describe('Rest URL options', () => {
const parentDropdown = new FormFieldModel(new FormModel(), { const parentDropdown = new FormFieldModel(new FormModel(), {
id: 'parentDropdown', id: 'parentDropdown',
type: 'dropdown', type: 'dropdown',
@@ -716,7 +692,6 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => { describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => {
it('should load the selection of a manual type linked dropdown', () => { 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' }), {
id: 'child-dropdown-id', id: 'child-dropdown-id',
@@ -737,7 +712,7 @@ describe('DropdownCloudWidgetComponent', () => {
expect(updateFormSpy).toHaveBeenCalled(); expect(updateFormSpy).toHaveBeenCalled();
expect(widget.field.options).toEqual(mockConditionalEntries[1].options); expect(widget.field.options).toEqual(mockConditionalEntries[1].options);
expect(widget.field.form.values).toEqual({ 'child-dropdown-id': { id: 'MI', name: 'MILAN' }}); expect(widget.field.form.values).toEqual({ 'child-dropdown-id': { id: 'MI', name: 'MILAN' } });
}); });
it('should load the selection of a rest type linked dropdown', () => { it('should load the selection of a rest type linked dropdown', () => {
@@ -767,7 +742,6 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
describe('when form model has left labels', () => { describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => { 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', leftLabels: true }), {
id: 'dropdown-id', id: 'dropdown-id',
@@ -838,8 +812,8 @@ describe('DropdownCloudWidgetComponent', () => {
optionsLabel: string, optionsLabel: string,
processVariables?: TaskVariableCloud[], processVariables?: TaskVariableCloud[],
variables?: TaskVariableCloud[] variables?: TaskVariableCloud[]
) => new FormFieldModel( ) =>
new FormModel({ taskId: 'fake-task-id', processVariables, variables }), { new FormFieldModel(new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
id: 'variable-dropdown-id', id: 'variable-dropdown-id',
name: 'variable-options-dropdown', name: 'variable-options-dropdown',
type: 'dropdown', type: 'dropdown',
@@ -865,7 +839,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should display options persisted from process variable', async () => { it('should display options persisted from process variable', async () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges(); fixture.detectChanges();
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' })); const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
await dropdown.open(); await dropdown.open();
@@ -913,7 +893,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should return empty array and display error when path is incorrect', () => { it('should return empty array and display error when path is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.wrongPath.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges(); fixture.detectChanges();
checkDropdownVariableOptionsFailed(); checkDropdownVariableOptionsFailed();
@@ -921,7 +907,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should return empty array and display error when id is incorrect', () => { it('should return empty array and display error when id is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'wrongId', 'playerFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'wrongId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges(); fixture.detectChanges();
checkDropdownVariableOptionsFailed(); checkDropdownVariableOptionsFailed();
@@ -929,7 +921,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should return empty array and display error when label is incorrect', () => { it('should return empty array and display error when label is incorrect', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.people.players', 'playerId', 'wrongFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.people.players',
'playerId',
'wrongFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges(); fixture.detectChanges();
checkDropdownVariableOptionsFailed(); checkDropdownVariableOptionsFailed();
@@ -937,7 +935,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should return empty array and display error when variable is NOT found', () => { it('should return empty array and display error when variable is NOT found', () => {
widget.field = getVariableDropdownWidget('variables.wrong-variable-id', 'response.people.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.wrong-variable-id',
'response.people.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
fixture.detectChanges(); fixture.detectChanges();
checkDropdownVariableOptionsFailed(); checkDropdownVariableOptionsFailed();
@@ -953,7 +957,13 @@ describe('DropdownCloudWidgetComponent', () => {
}); });
it('should NOT display errors if form is in the preview state', () => { it('should NOT display errors if form is in the preview state', () => {
widget.field = getVariableDropdownWidget('variables.json-variable', 'response.wrongPath.players', 'playerId', 'playerFullName', mockProcessVariablesWithJson); widget.field = getVariableDropdownWidget(
'variables.json-variable',
'response.wrongPath.players',
'playerId',
'playerFullName',
mockProcessVariablesWithJson
);
spyOn(formCloudService, 'getPreviewState').and.returnValue(true); spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
fixture.detectChanges(); fixture.detectChanges();