2016-06-23 12:47:54 -04:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2019-08-22 22:16:25 -04:00
|
|
|
import {AsyncPipe, ɵgetDOM as getDOM} from '@angular/common';
|
2017-03-01 13:28:52 -05:00
|
|
|
import {EventEmitter, WrappedValue} from '@angular/core';
|
2017-03-02 15:12:46 -05:00
|
|
|
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal';
|
|
|
|
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
import {SpyChangeDetectorRef} from '../spies';
|
|
|
|
|
2017-12-16 17:42:55 -05:00
|
|
|
{
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('AsyncPipe', () => {
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
describe('Observable', () => {
|
2016-11-12 08:08:58 -05:00
|
|
|
let emitter: EventEmitter<any>;
|
|
|
|
let pipe: AsyncPipe;
|
|
|
|
let ref: any;
|
|
|
|
const message = {};
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
emitter = new EventEmitter();
|
|
|
|
ref = new SpyChangeDetectorRef();
|
|
|
|
pipe = new AsyncPipe(ref);
|
|
|
|
});
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('transform', () => {
|
|
|
|
it('should return null when subscribing to an observable',
|
2015-08-04 14:55:21 -04:00
|
|
|
() => { expect(pipe.transform(emitter)).toBe(null); });
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should return the latest available value wrapped',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
2016-08-02 18:53:34 -04:00
|
|
|
emitter.emit(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2015-08-04 14:55:21 -04:00
|
|
|
expect(pipe.transform(emitter)).toEqual(new WrappedValue(message));
|
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, 0);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-05-25 20:16:50 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should return same value when nothing has changed since the last call',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
2016-08-02 18:53:34 -04:00
|
|
|
emitter.emit(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
|
|
|
expect(pipe.transform(emitter)).toBe(message);
|
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, 0);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should dispose of the existing subscription when subscribing to a new observable',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
|
|
|
|
2016-11-12 08:08:58 -05:00
|
|
|
const newEmitter = new EventEmitter();
|
2015-08-04 14:55:21 -04:00
|
|
|
expect(pipe.transform(newEmitter)).toBe(null);
|
2016-08-02 18:53:34 -04:00
|
|
|
emitter.emit(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
// this should not affect the pipe
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2015-08-04 14:55:21 -04:00
|
|
|
expect(pipe.transform(newEmitter)).toBe(null);
|
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, 0);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should request a change detection check upon receiving a new value',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
2016-08-02 18:53:34 -04:00
|
|
|
emitter.emit(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2015-08-28 13:08:18 -04:00
|
|
|
expect(ref.spy('markForCheck')).toHaveBeenCalled();
|
2015-08-04 14:55:21 -04:00
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, 10);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
2019-04-16 10:32:54 -04:00
|
|
|
|
|
|
|
it('should return unwrapped value for unchanged NaN', () => {
|
|
|
|
const emitter = new EventEmitter<any>();
|
|
|
|
emitter.emit(null);
|
|
|
|
pipe.transform(emitter);
|
|
|
|
emitter.next(NaN);
|
|
|
|
const firstResult = pipe.transform(emitter);
|
|
|
|
const secondResult = pipe.transform(emitter);
|
|
|
|
expect(firstResult instanceof WrappedValue).toBe(true);
|
|
|
|
expect((firstResult as WrappedValue).wrapped).toBeNaN();
|
|
|
|
expect(secondResult).toBeNaN();
|
|
|
|
});
|
2015-08-04 14:55:21 -04:00
|
|
|
});
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('ngOnDestroy', () => {
|
|
|
|
it('should do nothing when no subscription',
|
2015-11-17 13:09:23 -05:00
|
|
|
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should dispose of the existing subscription',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2015-08-04 14:55:21 -04:00
|
|
|
pipe.transform(emitter);
|
2015-11-17 13:09:23 -05:00
|
|
|
pipe.ngOnDestroy();
|
2016-08-02 18:53:34 -04:00
|
|
|
emitter.emit(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2015-08-04 14:55:21 -04:00
|
|
|
expect(pipe.transform(emitter)).toBe(null);
|
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, 0);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('Promise', () => {
|
2019-10-16 20:46:50 -04:00
|
|
|
const message = {};
|
2016-11-12 08:08:58 -05:00
|
|
|
let pipe: AsyncPipe;
|
|
|
|
let resolve: (result: any) => void;
|
|
|
|
let reject: (error: any) => void;
|
|
|
|
let promise: Promise<any>;
|
|
|
|
let ref: SpyChangeDetectorRef;
|
2015-08-04 14:55:21 -04:00
|
|
|
// adds longer timers for passing tests in IE
|
2016-11-12 08:08:58 -05:00
|
|
|
const timer = (getDOM() && browserDetection.isIE) ? 50 : 10;
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
beforeEach(() => {
|
2016-08-02 18:53:34 -04:00
|
|
|
promise = new Promise((res, rej) => {
|
|
|
|
resolve = res;
|
|
|
|
reject = rej;
|
|
|
|
});
|
2015-08-04 14:55:21 -04:00
|
|
|
ref = new SpyChangeDetectorRef();
|
2016-02-19 14:49:31 -05:00
|
|
|
pipe = new AsyncPipe(<any>ref);
|
2015-08-04 14:55:21 -04:00
|
|
|
});
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('transform', () => {
|
|
|
|
it('should return null when subscribing to a promise',
|
2016-08-02 18:53:34 -04:00
|
|
|
() => { expect(pipe.transform(promise)).toBe(null); });
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should return the latest available value',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2016-08-02 18:53:34 -04:00
|
|
|
pipe.transform(promise);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
resolve(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
expect(pipe.transform(promise)).toEqual(new WrappedValue(message));
|
2015-08-04 14:55:21 -04:00
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, timer);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should return unwrapped value when nothing has changed since the last call',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2016-08-02 18:53:34 -04:00
|
|
|
pipe.transform(promise);
|
|
|
|
resolve(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
pipe.transform(promise);
|
|
|
|
expect(pipe.transform(promise)).toBe(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, timer);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should dispose of the existing subscription when subscribing to a new promise',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2016-08-02 18:53:34 -04:00
|
|
|
pipe.transform(promise);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-11-12 08:08:58 -05:00
|
|
|
promise = new Promise<any>(() => {});
|
2016-08-02 18:53:34 -04:00
|
|
|
expect(pipe.transform(promise)).toBe(null);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
// this should not affect the pipe, so it should return WrappedValue
|
2016-08-02 18:53:34 -04:00
|
|
|
resolve(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
expect(pipe.transform(promise)).toBe(null);
|
2015-08-04 14:55:21 -04:00
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, timer);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should request a change detection check upon receiving a new value',
|
2016-06-09 14:04:15 -04:00
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2016-11-12 08:08:58 -05:00
|
|
|
const markForCheck = ref.spy('markForCheck');
|
2016-08-02 18:53:34 -04:00
|
|
|
pipe.transform(promise);
|
|
|
|
resolve(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
2016-02-25 17:24:17 -05:00
|
|
|
expect(markForCheck).toHaveBeenCalled();
|
2015-08-04 14:55:21 -04:00
|
|
|
async.done();
|
2016-07-21 20:12:00 -04:00
|
|
|
}, timer);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
describe('ngOnDestroy', () => {
|
|
|
|
it('should do nothing when no source',
|
2015-11-17 13:09:23 -05:00
|
|
|
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
|
2015-08-04 14:55:21 -04:00
|
|
|
|
2016-06-08 19:38:52 -04:00
|
|
|
it('should dispose of the existing source',
|
|
|
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
2016-08-02 18:53:34 -04:00
|
|
|
pipe.transform(promise);
|
|
|
|
expect(pipe.transform(promise)).toBe(null);
|
|
|
|
resolve(message);
|
2015-08-04 14:55:21 -04:00
|
|
|
|
|
|
|
|
2016-08-02 18:53:34 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
expect(pipe.transform(promise)).toEqual(new WrappedValue(message));
|
2016-06-08 19:38:52 -04:00
|
|
|
pipe.ngOnDestroy();
|
2016-08-02 18:53:34 -04:00
|
|
|
expect(pipe.transform(promise)).toBe(null);
|
2016-06-08 19:38:52 -04:00
|
|
|
async.done();
|
|
|
|
}, timer);
|
2015-08-04 14:55:21 -04:00
|
|
|
}));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('null', () => {
|
|
|
|
it('should return null when given null', () => {
|
2017-03-24 12:54:02 -04:00
|
|
|
const pipe = new AsyncPipe(null as any);
|
2016-04-22 18:33:32 -04:00
|
|
|
expect(pipe.transform(null)).toEqual(null);
|
2015-08-04 14:55:21 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('other types', () => {
|
|
|
|
it('should throw when given an invalid object', () => {
|
2017-03-24 12:54:02 -04:00
|
|
|
const pipe = new AsyncPipe(null as any);
|
2016-06-08 19:38:52 -04:00
|
|
|
expect(() => pipe.transform(<any>'some bogus object')).toThrowError();
|
2015-08-04 14:55:21 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|