Skip to content

Commit

Permalink
fix(forms): async validator-directives process Observables correctly (#…
Browse files Browse the repository at this point in the history
…8186)

Closes #/8022
  • Loading branch information
choeller authored and kara committed Jun 26, 2016
1 parent 9f00a1b commit eef9512
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function normalizeValidator(validator: ValidatorFn | Validator): Validato

export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
if ((<Validator>validator).validate !== undefined) {
return (c: AbstractControl) => Promise.resolve((<Validator>validator).validate(c));
return (c: AbstractControl) => (<Validator>validator).validate(c);
} else {
return <AsyncValidatorFn>validator;
}
Expand Down
25 changes: 25 additions & 0 deletions modules/@angular/common/test/forms-deprecated/validators_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import {AbstractControl, Control, ControlArray, ControlGroup, Validators} from '@angular/common/src/forms-deprecated';
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {Observable} from 'rxjs/Observable';

import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async';
import {PromiseWrapper} from '../../src/facade/promise';
import {normalizeAsyncValidator} from '../../src/forms-deprecated/directives/normalize_validator';

export function main() {
function validator(key: string, error: any) {
Expand All @@ -22,6 +24,18 @@ export function main() {
}
}

class AsyncValidatorDirective {
constructor(private expected: string, private error: any) {}

validate(c: any): {[key: string]: any;} {
return Observable.create((obs: any) => {
const error = this.expected !== c.value ? this.error : null;
obs.next(error);
obs.complete();
});
}
}

describe('Validators', () => {
describe('required', () => {
it('should error on an empty string',
Expand Down Expand Up @@ -88,6 +102,17 @@ export function main() {
});
});

it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => {
const c = Validators.composeAsync(
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]);

let value: any = null;
c(new Control()).then((v: any) => value = v);
tick(1);

expect(value).toEqual({'one': true});
}));

describe('compose', () => {
it('should return null when given null',
() => { expect(Validators.compose(null)).toBe(null); });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function normalizeValidator(validator: ValidatorFn | Validator): Validato

export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
if ((<Validator>validator).validate !== undefined) {
return (c: AbstractControl) => Promise.resolve((<Validator>validator).validate(c));
return (c: AbstractControl) => (<Validator>validator).validate(c);
} else {
return <AsyncValidatorFn>validator;
}
Expand Down
26 changes: 25 additions & 1 deletion modules/@angular/forms/test/validators_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {AbstractControl, FormControl, Validators} from '@angular/forms';
import {Observable} from 'rxjs/Observable';

import {normalizeAsyncValidator} from '../src/directives/normalize_validator';
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../src/facade/async';
import {PromiseWrapper} from '../src/facade/promise';

Expand All @@ -22,6 +24,18 @@ export function main() {
}
}

class AsyncValidatorDirective {
constructor(private expected: string, private error: any) {}

validate(c: any): {[key: string]: any;} {
return Observable.create((obs: any) => {
const error = this.expected !== c.value ? this.error : null;
obs.next(error);
obs.complete();
});
}
}

describe('Validators', () => {
describe('required', () => {
it('should error on an empty string',
Expand Down Expand Up @@ -147,12 +161,22 @@ export function main() {
expect(value).toEqual({'one': true, 'two': true});
}));

it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => {
const c = Validators.composeAsync(
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]);

let value: any = null;
c(new FormControl()).then((v: any) => value = v);
tick(1);

expect(value).toEqual({'one': true});
}));

it('should return null when no errors', fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator('expected', {'one': true})]);

var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new FormControl('expected'))).then(v => value = v);

tick(1);

expect(value).toEqual(null);
Expand Down

0 comments on commit eef9512

Please sign in to comment.