mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-5464] [form]Mandatory field validations are not applied once content removed (#7255)
* [ADF-5464] [form]Mandatory field validations are not applied once content is removed from these fields * * fix test and people widget * * fix flaky test
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
<div class="adf-group-widget {{field.className}}"
|
<div class="adf-group-widget {{field.className}}"
|
||||||
[class.is-dirty]="value"
|
[class.is-dirty]="!!field.value"
|
||||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="functional-group-div">
|
[class.adf-invalid]="!field.isValid"
|
||||||
|
[class.adf-readonly]="field.readOnly"
|
||||||
|
id="functional-group-div">
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span *ngIf="isRequired()">*</span></label>
|
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span *ngIf="isRequired()">*</span></label>
|
||||||
<input matInput
|
<input matInput
|
||||||
@@ -8,15 +11,14 @@
|
|||||||
type="text"
|
type="text"
|
||||||
data-automation-id="adf-group-search-input"
|
data-automation-id="adf-group-search-input"
|
||||||
[id]="field.id"
|
[id]="field.id"
|
||||||
[(ngModel)]="value"
|
[formControl]="searchTerm"
|
||||||
(keyup)="onKeyUp($event)"
|
[placeholder]="field.placeholder"
|
||||||
[disabled]="field.readOnly"
|
|
||||||
placeholder="{{field.placeholder}}"
|
|
||||||
[matAutocomplete]="auto">
|
[matAutocomplete]="auto">
|
||||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="onItemSelect($event.option.value)">
|
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="updateOption($event.option.value)" [displayWith]="getDisplayName">
|
||||||
<mat-option *ngFor="let item of groups; let i = index" id="adf-group-widget-user-{{i}}"
|
<mat-option *ngFor="let item of groups$ | async; let i = index"
|
||||||
|
id="adf-group-widget-user-{{i}}"
|
||||||
[id]="field.id +'-'+item.id"
|
[id]="field.id +'-'+item.id"
|
||||||
(click)="onItemClick(item, $event)" [value]="item">
|
[value]="item">
|
||||||
<span id="adf-group-label-name">{{item.name}}</span>
|
<span id="adf-group-label-name">{{item.name}}</span>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
|
@@ -15,23 +15,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ElementRef } from '@angular/core';
|
import { of, timer } from 'rxjs';
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { FormService } from '../../../services/form.service';
|
import { FormService } from '../../../services/form.service';
|
||||||
import { FormFieldModel } from '../core/form-field.model';
|
import { FormFieldModel } from '../core/form-field.model';
|
||||||
import { FormModel } from '../core/form.model';
|
import { FormModel } from '../core/form.model';
|
||||||
import { GroupModel } from '../core/group.model';
|
import { GroupModel } from '../core/group.model';
|
||||||
import { FunctionalGroupWidgetComponent } from './functional-group.widget';
|
import { FunctionalGroupWidgetComponent } from './functional-group.widget';
|
||||||
import { AlfrescoApiService } from '../../../../services';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
import { CoreTestingModule, setupTestBed } from '../../../../testing';
|
import { CoreTestingModule, setupTestBed } from '../../../../testing';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
describe('FunctionalGroupWidgetComponent', () => {
|
describe('FunctionalGroupWidgetComponent', () => {
|
||||||
|
let fixture: ComponentFixture<FunctionalGroupWidgetComponent>;
|
||||||
|
let component: FunctionalGroupWidgetComponent;
|
||||||
let formService: FormService;
|
let formService: FormService;
|
||||||
let elementRef: ElementRef;
|
let getWorkflowGroupsSpy: jasmine.Spy;
|
||||||
let widget: FunctionalGroupWidgetComponent;
|
const groups: GroupModel[] = [
|
||||||
let alfrescoApiService: AlfrescoApiService;
|
{ id: '1', name: 'group 1' },
|
||||||
|
{ id: '2', name: 'group 2' }
|
||||||
|
];
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -41,170 +43,109 @@ describe('FunctionalGroupWidgetComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
formService = TestBed.inject(FormService);
|
||||||
|
getWorkflowGroupsSpy = spyOn(formService, 'getWorkflowGroups').and.returnValue(of([]));
|
||||||
|
|
||||||
formService = new FormService(null, alfrescoApiService, null);
|
fixture = TestBed.createComponent(FunctionalGroupWidgetComponent);
|
||||||
elementRef = new ElementRef(null);
|
component = fixture.componentInstance;
|
||||||
widget = new FunctionalGroupWidgetComponent(formService, elementRef);
|
component.field = new FormFieldModel(new FormModel());
|
||||||
widget.field = new FormFieldModel(new FormModel());
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setup text from underlying field on init', () => {
|
afterEach(() => {
|
||||||
|
getWorkflowGroupsSpy.calls.reset();
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function typeIntoInput(text: string) {
|
||||||
|
component.searchTerm.setValue(text);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
await timer(300).toPromise();
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const input = fixture.nativeElement.querySelector('input');
|
||||||
|
input.focus();
|
||||||
|
input.dispatchEvent(new Event('focusin'));
|
||||||
|
input.dispatchEvent(new Event('input'));
|
||||||
|
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should setup text from underlying field on init', async () => {
|
||||||
const group: GroupModel = { name: 'group-1'};
|
const group: GroupModel = { name: 'group-1'};
|
||||||
widget.field.value = group;
|
component.field.value = group;
|
||||||
|
component.ngOnInit();
|
||||||
|
|
||||||
spyOn(formService, 'getWorkflowGroups').and.returnValue(
|
expect(component.searchTerm.value).toEqual(group.name);
|
||||||
new Observable((observer) => {
|
|
||||||
observer.next(null);
|
|
||||||
observer.complete();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
widget.ngOnInit();
|
|
||||||
expect(formService.getWorkflowGroups).toHaveBeenCalled();
|
|
||||||
expect(widget.value).toBe(group.name);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not setup text on init', () => {
|
it('should not setup text on init', () => {
|
||||||
widget.field.value = null;
|
component.field.value = null;
|
||||||
widget.ngOnInit();
|
component.ngOnInit();
|
||||||
expect(widget.value).toBeUndefined();
|
expect(component.searchTerm.value).toBeNull();
|
||||||
});
|
|
||||||
|
|
||||||
it('should require form field to setup values on init', () => {
|
|
||||||
widget.field = null;
|
|
||||||
widget.ngOnInit();
|
|
||||||
|
|
||||||
expect(widget.value).toBeUndefined();
|
|
||||||
expect(widget.groupId).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setup group restriction', () => {
|
it('should setup group restriction', () => {
|
||||||
widget.ngOnInit();
|
component.ngOnInit();
|
||||||
expect(widget.groupId).toBeUndefined();
|
expect(component.groupId).toBeUndefined();
|
||||||
|
|
||||||
widget.field.params = { restrictWithGroup: { id: '<id>' } };
|
component.field.params = { restrictWithGroup: { id: '<id>' } };
|
||||||
widget.ngOnInit();
|
component.ngOnInit();
|
||||||
expect(widget.groupId).toBe('<id>');
|
expect(component.groupId).toBe('<id>');
|
||||||
});
|
|
||||||
|
|
||||||
it('should prevent default behaviour on option item click', () => {
|
|
||||||
const event = jasmine.createSpyObj('event', ['preventDefault']);
|
|
||||||
widget.onItemClick(null, event);
|
|
||||||
expect(event.preventDefault).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update values on item click', () => {
|
|
||||||
const item: GroupModel = { name: 'group-1' };
|
|
||||||
|
|
||||||
widget.onItemClick(item, null);
|
|
||||||
expect(widget.field.value).toBe(item);
|
|
||||||
expect(widget.value).toBe(item.name);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update form on value flush', () => {
|
it('should update form on value flush', () => {
|
||||||
spyOn(widget.field, 'updateForm').and.callThrough();
|
spyOn(component.field, 'updateForm').and.callThrough();
|
||||||
widget.flushValue();
|
component.updateOption();
|
||||||
expect(widget.field.updateForm).toHaveBeenCalled();
|
expect(component.field.updateForm).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should flush selected value', () => {
|
it('should flush selected value', () => {
|
||||||
const groups: GroupModel[] = [
|
getWorkflowGroupsSpy.and.returnValue(of(groups));
|
||||||
{ id: '1', name: 'group 1' },
|
|
||||||
{ id: '2', name: 'group 2' }
|
|
||||||
];
|
|
||||||
|
|
||||||
widget.groups = groups;
|
component.updateOption(groups[1]);
|
||||||
widget.value = 'group 2';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBe(groups[1].name);
|
expect(component.field.value).toBe(groups[1]);
|
||||||
expect(widget.field.value).toBe(groups[1]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be case insensitive when flushing value', () => {
|
it('should fetch groups and show popup on key up', async () => {
|
||||||
const groups: GroupModel[] = [
|
component.groupId = 'parentGroup';
|
||||||
{ id: '1', name: 'group 1' },
|
getWorkflowGroupsSpy.and.returnValue(of(groups));
|
||||||
{ id: '2', name: 'gRoUp 2' }
|
|
||||||
];
|
|
||||||
|
|
||||||
widget.groups = groups;
|
await typeIntoInput('group');
|
||||||
widget.value = 'GROUP 2';
|
|
||||||
widget.flushValue();
|
|
||||||
|
|
||||||
expect(widget.value).toBe(groups[1].name);
|
const options: HTMLElement[] = Array.from(document.querySelectorAll('[id="adf-group-label-name"]'));
|
||||||
expect(widget.field.value).toBe(groups[1]);
|
expect(options.map(option => option.innerText)).toEqual(['group 1', 'group 2']);
|
||||||
|
expect(getWorkflowGroupsSpy).toHaveBeenCalledWith('group', 'parentGroup');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch groups and show popup on key up', () => {
|
it('should hide popup when fetching empty group list', async () => {
|
||||||
const groups: GroupModel[] = [{}, {}];
|
component.groupId = 'parentGroup';
|
||||||
spyOn(formService, 'getWorkflowGroups').and.returnValue(
|
getWorkflowGroupsSpy.and.returnValues(of(groups), of([]));
|
||||||
new Observable((observer) => {
|
|
||||||
observer.next(groups);
|
|
||||||
observer.complete();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const keyboardEvent = new KeyboardEvent('keypress');
|
await typeIntoInput('group');
|
||||||
widget.value = 'group';
|
|
||||||
widget.onKeyUp(keyboardEvent);
|
|
||||||
|
|
||||||
expect(formService.getWorkflowGroups).toHaveBeenCalledWith('group', undefined);
|
let options: HTMLElement[] = Array.from(document.querySelectorAll('[id="adf-group-label-name"]'));
|
||||||
expect(widget.groups).toBe(groups);
|
expect(options.map(option => option.innerText)).toEqual(['group 1', 'group 2']);
|
||||||
|
|
||||||
|
await typeIntoInput('unknown-group');
|
||||||
|
|
||||||
|
options = Array.from(document.querySelectorAll('[id="adf-group-label-name"]'));
|
||||||
|
expect(options).toEqual([]);
|
||||||
|
expect(getWorkflowGroupsSpy).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch groups with a group filter', () => {
|
it('should not fetch groups when value is missing', async () => {
|
||||||
const groups: GroupModel[] = [{}, {}];
|
await typeIntoInput('');
|
||||||
spyOn(formService, 'getWorkflowGroups').and.returnValue(
|
expect(getWorkflowGroupsSpy).not.toHaveBeenCalled();
|
||||||
new Observable((observer) => {
|
|
||||||
observer.next(groups);
|
|
||||||
observer.complete();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const keyboardEvent = new KeyboardEvent('keypress');
|
|
||||||
widget.groupId = 'parentGroup';
|
|
||||||
widget.value = 'group';
|
|
||||||
widget.onKeyUp(keyboardEvent);
|
|
||||||
|
|
||||||
expect(formService.getWorkflowGroups).toHaveBeenCalledWith('group', 'parentGroup');
|
|
||||||
expect(widget.groups).toBe(groups);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide popup when fetching empty group list', () => {
|
it('should not fetch groups when value violates constraints', async () => {
|
||||||
spyOn(formService, 'getWorkflowGroups').and.returnValue(
|
component.minTermLength = 4;
|
||||||
new Observable((observer) => {
|
await typeIntoInput('123');
|
||||||
observer.next(null);
|
expect(getWorkflowGroupsSpy).not.toHaveBeenCalled();
|
||||||
observer.complete();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const keyboardEvent = new KeyboardEvent('keypress');
|
|
||||||
widget.value = 'group';
|
|
||||||
widget.onKeyUp(keyboardEvent);
|
|
||||||
|
|
||||||
expect(formService.getWorkflowGroups).toHaveBeenCalledWith('group', undefined);
|
|
||||||
expect(widget.groups.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not fetch groups when value is missing', () => {
|
|
||||||
spyOn(formService, 'getWorkflowGroups').and.stub();
|
|
||||||
|
|
||||||
const keyboardEvent = new KeyboardEvent('keypress');
|
|
||||||
widget.value = null;
|
|
||||||
widget.onKeyUp(keyboardEvent);
|
|
||||||
|
|
||||||
expect(formService.getWorkflowGroups).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not fetch groups when value violates constraints', () => {
|
|
||||||
spyOn(formService, 'getWorkflowGroups').and.stub();
|
|
||||||
|
|
||||||
const keyboardEvent = new KeyboardEvent('keypress');
|
|
||||||
widget.minTermLength = 4;
|
|
||||||
widget.value = '123';
|
|
||||||
widget.onKeyUp(keyboardEvent);
|
|
||||||
|
|
||||||
expect(formService.getWorkflowGroups).not.toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -17,11 +17,13 @@
|
|||||||
|
|
||||||
/* tslint:disable:component-selector */
|
/* tslint:disable:component-selector */
|
||||||
|
|
||||||
import { ENTER, ESCAPE } from '@angular/cdk/keycodes';
|
|
||||||
import { Component, ElementRef, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, ElementRef, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { FormService } from '../../../services/form.service';
|
import { FormService } from '../../../services/form.service';
|
||||||
import { GroupModel } from './../core/group.model';
|
import { GroupModel } from './../core/group.model';
|
||||||
import { WidgetComponent } from './../widget.component';
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
import { catchError, debounceTime, filter, switchMap, tap } from 'rxjs/operators';
|
||||||
|
import { merge, of } from 'rxjs';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'functional-group-widget',
|
selector: 'functional-group-widget',
|
||||||
@@ -42,11 +44,21 @@ import { WidgetComponent } from './../widget.component';
|
|||||||
})
|
})
|
||||||
export class FunctionalGroupWidgetComponent extends WidgetComponent implements OnInit {
|
export class FunctionalGroupWidgetComponent extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
value: string;
|
|
||||||
oldValue: string;
|
|
||||||
groups: GroupModel[] = [];
|
|
||||||
minTermLength: number = 1;
|
minTermLength: number = 1;
|
||||||
groupId: string;
|
groupId: string;
|
||||||
|
searchTerm = new FormControl();
|
||||||
|
groups$ = merge(this.searchTerm.valueChanges).pipe(
|
||||||
|
tap((search: GroupModel | string) => {
|
||||||
|
const isValid = typeof search !== 'string';
|
||||||
|
const empty = search === '';
|
||||||
|
this.updateOption( isValid ? search as GroupModel : null );
|
||||||
|
this.validateGroup(isValid, empty);
|
||||||
|
}),
|
||||||
|
filter((group: string | GroupModel) => typeof group === 'string' && group.length >= this.minTermLength),
|
||||||
|
debounceTime(300),
|
||||||
|
switchMap((searchTerm: string) => this.formService.getWorkflowGroups(searchTerm, this.groupId)
|
||||||
|
.pipe(catchError(() => of([]))))
|
||||||
|
);
|
||||||
|
|
||||||
constructor(public formService: FormService,
|
constructor(public formService: FormService,
|
||||||
public elementRef: ElementRef) {
|
public elementRef: ElementRef) {
|
||||||
@@ -55,65 +67,52 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.field) {
|
if (this.field) {
|
||||||
const group = this.field.value;
|
|
||||||
if (group) {
|
if (this.field.readOnly) {
|
||||||
this.value = group.name;
|
this.searchTerm.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = this.field.params;
|
const params = this.field.params;
|
||||||
if (params && params['restrictWithGroup']) {
|
if (params && params.restrictWithGroup) {
|
||||||
const restrictWithGroup = <GroupModel> params['restrictWithGroup'];
|
const restrictWithGroup = <GroupModel> params.restrictWithGroup;
|
||||||
this.groupId = restrictWithGroup.id;
|
this.groupId = restrictWithGroup.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load auto-completion for previously saved value
|
if (this.field.value?.name) {
|
||||||
if (this.value) {
|
this.searchTerm.setValue(this.field.value.name);
|
||||||
this.formService
|
|
||||||
.getWorkflowGroups(this.value, this.groupId)
|
|
||||||
.subscribe(groups => this.groups = groups || []);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyUp(event: KeyboardEvent) {
|
updateOption(option?: GroupModel) {
|
||||||
if (this.value && this.value.length >= this.minTermLength && this.oldValue !== this.value) {
|
|
||||||
if (event.keyCode !== ESCAPE && event.keyCode !== ENTER) {
|
|
||||||
this.oldValue = this.value;
|
|
||||||
this.formService
|
|
||||||
.getWorkflowGroups(this.value, this.groupId)
|
|
||||||
.subscribe(groups => this.groups = groups || []);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flushValue() {
|
|
||||||
const option = this.groups.find((item) => item.name.toLocaleLowerCase() === this.value.toLocaleLowerCase());
|
|
||||||
|
|
||||||
if (option) {
|
if (option) {
|
||||||
this.field.value = option;
|
this.field.value = option;
|
||||||
this.value = option.name;
|
|
||||||
} else {
|
} else {
|
||||||
this.field.value = null;
|
this.field.value = null;
|
||||||
this.value = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.field.updateForm();
|
this.field.updateForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemClick(item: GroupModel, event: Event) {
|
validateGroup(valid: boolean, empty: boolean) {
|
||||||
if (item) {
|
const isEmpty = !this.field.required && (empty || valid);
|
||||||
this.field.value = item;
|
const hasValue = this.field.required && valid;
|
||||||
this.value = item.name;
|
|
||||||
}
|
if (hasValue || isEmpty) {
|
||||||
if (event) {
|
this.field.validationSummary.message = '';
|
||||||
event.preventDefault();
|
this.field.validate();
|
||||||
|
this.field.form.validateForm();
|
||||||
|
} else {
|
||||||
|
this.field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_VALUE';
|
||||||
|
this.field.markAsInvalid();
|
||||||
|
this.field.form.markAsInvalid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemSelect(item: GroupModel) {
|
getDisplayName(model: GroupModel | string) {
|
||||||
if (item) {
|
if (model) {
|
||||||
this.field.value = item;
|
return typeof model === 'string' ? model : model.name;
|
||||||
this.value = item.name;
|
|
||||||
}
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
[id]="field.id"
|
[id]="field.id"
|
||||||
[formControl]="searchTerm"
|
[formControl]="searchTerm"
|
||||||
placeholder="{{field.placeholder}}"
|
[placeholder]="field.placeholder"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
[matTooltip]="field.tooltip"
|
[matTooltip]="field.tooltip"
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
|
@@ -180,10 +180,11 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
element = fixture.nativeElement;
|
element = fixture.nativeElement;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
if (fixture) {
|
|
||||||
fixture.destroy();
|
|
||||||
}
|
|
||||||
TestBed.resetTestingModule();
|
TestBed.resetTestingModule();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,17 +220,18 @@ describe('PeopleWidgetComponent', () => {
|
|||||||
expect(fixture.debugElement.query(By.css('#adf-people-widget-user-1'))).not.toBeNull();
|
expect(fixture.debugElement.query(By.css('#adf-people-widget-user-1'))).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide result list if input is empty', () => {
|
it('should hide result list if input is empty', async () => {
|
||||||
const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||||
peopleHTMLElement.focus();
|
peopleHTMLElement.focus();
|
||||||
peopleHTMLElement.value = '';
|
peopleHTMLElement.value = '';
|
||||||
peopleHTMLElement.dispatchEvent(new Event('keyup'));
|
peopleHTMLElement.dispatchEvent(new Event('keyup'));
|
||||||
|
peopleHTMLElement.dispatchEvent(new Event('focusin'));
|
||||||
peopleHTMLElement.dispatchEvent(new Event('input'));
|
peopleHTMLElement.dispatchEvent(new Event('input'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
fixture.whenStable().then(() => {
|
await fixture.whenStable();
|
||||||
fixture.detectChanges();
|
|
||||||
expect(fixture.debugElement.query(By.css('#adf-people-widget-user-0'))).toBeNull();
|
expect(fixture.debugElement.query(By.css('#adf-people-widget-user-0'))).toBeNull();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display two options if we tap one letter', async () => {
|
it('should display two options if we tap one letter', async () => {
|
||||||
|
@@ -55,29 +55,25 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
input: ElementRef;
|
input: ElementRef;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
peopleSelected: EventEmitter<number>;
|
peopleSelected: EventEmitter<number> = new EventEmitter();
|
||||||
|
|
||||||
groupId: string;
|
groupId: string;
|
||||||
value: any;
|
value: any;
|
||||||
|
|
||||||
searchTerm = new FormControl();
|
searchTerm = new FormControl();
|
||||||
errorMsg = '';
|
|
||||||
searchTerms$: Observable<any> = this.searchTerm.valueChanges;
|
searchTerms$: Observable<any> = this.searchTerm.valueChanges;
|
||||||
|
|
||||||
users$ = this.searchTerms$.pipe(
|
users$ = this.searchTerms$.pipe(
|
||||||
tap(() => {
|
tap((searchInput) => {
|
||||||
this.errorMsg = '';
|
if (typeof searchInput === 'string') {
|
||||||
|
this.onItemSelect();
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
switchMap((searchTerm) => {
|
switchMap((searchTerm) => {
|
||||||
const value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm;
|
const value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm;
|
||||||
return this.formService.getWorkflowUsers(value, this.groupId)
|
return this.formService.getWorkflowUsers(value, this.groupId)
|
||||||
.pipe(
|
.pipe(catchError(() => of([])));
|
||||||
catchError((err) => {
|
|
||||||
this.errorMsg = err.message;
|
|
||||||
return of();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
map((list: UserProcessModel[]) => {
|
map((list: UserProcessModel[]) => {
|
||||||
const value = this.searchTerm.value.email ? this.getDisplayName(this.searchTerm.value) : this.searchTerm.value;
|
const value = this.searchTerm.value.email ? this.getDisplayName(this.searchTerm.value) : this.searchTerm.value;
|
||||||
@@ -88,7 +84,6 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(public formService: FormService, public peopleProcessService: PeopleProcessService) {
|
constructor(public formService: FormService, public peopleProcessService: PeopleProcessService) {
|
||||||
super(formService);
|
super(formService);
|
||||||
this.peopleSelected = new EventEmitter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -122,13 +117,13 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
|
|
||||||
isValidUser(users: UserProcessModel[], name: string): boolean {
|
isValidUser(users: UserProcessModel[], name: string): boolean {
|
||||||
if (users) {
|
if (users) {
|
||||||
return users.find((user) => {
|
return !!users.find((user) => {
|
||||||
const selectedUser = this.getDisplayName(user).toLocaleLowerCase() === name.toLocaleLowerCase();
|
const selectedUser = this.getDisplayName(user).toLocaleLowerCase() === name.toLocaleLowerCase();
|
||||||
if (selectedUser) {
|
if (selectedUser) {
|
||||||
this.peopleSelected.emit(user && user.id || undefined);
|
this.peopleSelected.emit(user && user.id || undefined);
|
||||||
}
|
}
|
||||||
return selectedUser;
|
return selectedUser;
|
||||||
}) ? true : false;
|
});
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -141,9 +136,11 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemSelect(item: UserProcessModel) {
|
onItemSelect(item?: UserProcessModel) {
|
||||||
if (item) {
|
if (item) {
|
||||||
this.field.value = item;
|
this.field.value = item;
|
||||||
|
} else {
|
||||||
|
this.field.value = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user