import { HttpClientTestingModule } from '@angular/common/http/testing';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { BsModalService } from 'ngx-bootstrap/modal';
-import { of as observableOf } from 'rxjs';
+import { Observable, of as observableOf } from 'rxjs';
import { configureTestBed } from '../../../../testing/unit-test-helper';
import { RgwUserService } from '../../../shared/api/rgw-user.service';
it('should validate user id (1/3)', () => {
const validatorFn = component.userIdValidator();
const ctrl = new FormControl('');
- const validatorPromise = validatorFn(ctrl);
- expect(validatorPromise instanceof Promise).toBeTruthy();
- if (validatorPromise instanceof Promise) {
- validatorPromise.then((resp) => {
+ const validator$ = validatorFn(ctrl);
+ expect(validator$ instanceof Observable).toBeTruthy();
+ if (validator$ instanceof Observable) {
+ validator$.subscribe((resp) => {
expect(resp).toBe(null);
});
}
});
- it('should validate user id (2/3)', () => {
- const validatorFn = component.userIdValidator();
- const ctrl = new FormControl('ab');
- ctrl.markAsDirty();
- const validatorPromise = validatorFn(ctrl);
- expect(validatorPromise instanceof Promise).toBeTruthy();
- if (validatorPromise instanceof Promise) {
- validatorPromise.then((resp) => {
- expect(resp).toBe(null);
- });
- }
- });
-
- it('should validate user id (3/3)', () => {
- queryResult = ['abc'];
- const validatorFn = component.userIdValidator();
- const ctrl = new FormControl('abc');
- ctrl.markAsDirty();
- const validatorPromise = validatorFn(ctrl);
- expect(validatorPromise instanceof Promise).toBeTruthy();
- if (validatorPromise instanceof Promise) {
- validatorPromise.then((resp) => {
- expect(resp instanceof Object).toBeTruthy();
- expect(resp.userIdExists).toBeTruthy();
- });
- }
- });
+ it(
+ 'should validate user id (2/3)',
+ fakeAsync(() => {
+ const validatorFn = component.userIdValidator(0);
+ const ctrl = new FormControl('ab');
+ ctrl.markAsDirty();
+ const validator$ = validatorFn(ctrl);
+ expect(validator$ instanceof Observable).toBeTruthy();
+ if (validator$ instanceof Observable) {
+ validator$.subscribe((resp) => {
+ expect(resp).toBe(null);
+ });
+ tick();
+ }
+ })
+ );
+
+ it(
+ 'should validate user id (3/3)',
+ fakeAsync(() => {
+ queryResult = ['abc'];
+ const validatorFn = component.userIdValidator(0);
+ const ctrl = new FormControl('abc');
+ ctrl.markAsDirty();
+ const validator$ = validatorFn(ctrl);
+ expect(validator$ instanceof Observable).toBeTruthy();
+ if (validator$ instanceof Observable) {
+ validator$.subscribe((resp) => {
+ expect(resp instanceof Object).toBeTruthy();
+ expect(resp.userIdExists).toBeTruthy();
+ });
+ tick();
+ }
+ })
+ );
});
});
import * as _ from 'lodash';
import { BsModalService } from 'ngx-bootstrap';
-import { forkJoin as observableForkJoin, Observable } from 'rxjs';
+import {
+ forkJoin as observableForkJoin,
+ Observable,
+ of as observableOf,
+ timer as observableTimer
+} from 'rxjs';
+import { map, switchMapTo, take } from 'rxjs/operators';
import { RgwUserService } from '../../../shared/api/rgw-user.service';
import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
/**
* Validate the username.
+ * @param {number|Date} dueTime The delay time to wait before the
+ * API call is executed. This is useful to prevent API calls on
+ * every keystroke. Defaults to 500.
*/
- userIdValidator(): AsyncValidatorFn {
+ userIdValidator(dueTime = 500): AsyncValidatorFn {
const rgwUserService = this.rgwUserService;
- return (control: AbstractControl): Promise<ValidationErrors | null> => {
- return new Promise((resolve) => {
- // Exit immediately if user has not interacted with the control yet
- // or the control value is empty.
- if (control.pristine || control.value === '') {
- resolve(null);
- return;
- }
- rgwUserService.exists(control.value).subscribe((resp: boolean) => {
+ return (control: AbstractControl): Observable<ValidationErrors | null> => {
+ // Exit immediately if user has not interacted with the control yet
+ // or the control value is empty.
+ if (control.pristine || control.value === '') {
+ return observableOf(null);
+ }
+ // Forgot previous requests if a new one arrives within the specified
+ // delay time.
+ return observableTimer(dueTime).pipe(
+ switchMapTo(rgwUserService.exists(control.value)),
+ map((resp: boolean) => {
if (!resp) {
- resolve(null);
+ return null;
} else {
- resolve({ userIdExists: true });
+ return { userIdExists: true };
}
- });
- });
+ }),
+ take(1)
+ );
};
}