refactor(test_lib): do not execute jasmine test as async if not required
fixes #3893
This commit is contained in:
parent
46f751bd2f
commit
44a991e245
|
@ -195,13 +195,7 @@ export function inject(tokens: any[], fn: Function): FunctionWithParamTokens {
|
|||
}
|
||||
|
||||
export class FunctionWithParamTokens {
|
||||
_tokens: any[];
|
||||
_fn: Function;
|
||||
|
||||
constructor(tokens: any[], fn: Function) {
|
||||
this._tokens = tokens;
|
||||
this._fn = fn;
|
||||
}
|
||||
constructor(private _tokens: any[], private _fn: Function) {}
|
||||
|
||||
/**
|
||||
* Returns the value of the executed function.
|
||||
|
@ -210,4 +204,6 @@ export class FunctionWithParamTokens {
|
|||
var params = ListWrapper.map(this._tokens, (t) => injector.get(t));
|
||||
return FunctionWrapper.apply(this._fn, params);
|
||||
}
|
||||
|
||||
hasToken(token: any): boolean { return this._tokens.indexOf(token) > -1; }
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||
import {StringMapWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {global} from 'angular2/src/core/facade/lang';
|
||||
import {global, isFunction} from 'angular2/src/core/facade/lang';
|
||||
import {NgZoneZone} from 'angular2/src/core/zone/ng_zone';
|
||||
|
||||
import {bind} from 'angular2/di';
|
||||
|
@ -18,6 +18,10 @@ var _global: jasmine.GlobalPolluter = <any>(typeof window === 'undefined' ? glob
|
|||
|
||||
export var afterEach = _global.afterEach;
|
||||
|
||||
type SyncTestFn = () => void;
|
||||
type AsyncTestFn = (done: () => void) => void;
|
||||
type AnyTestFn = SyncTestFn | AsyncTestFn;
|
||||
|
||||
export interface NgMatchers extends jasmine.Matchers {
|
||||
toBe(expected: any): boolean;
|
||||
toEqual(expected: any): boolean;
|
||||
|
@ -34,11 +38,9 @@ export interface NgMatchers extends jasmine.Matchers {
|
|||
export var expect: (actual: any) => NgMatchers = <any>_global.expect;
|
||||
|
||||
export class AsyncTestCompleter {
|
||||
_done: Function;
|
||||
constructor(private _done: Function) {}
|
||||
|
||||
constructor(done: Function) { this._done = done; }
|
||||
|
||||
done() { this._done(); }
|
||||
done(): void { this._done(); }
|
||||
}
|
||||
|
||||
var jsmBeforeEach = _global.beforeEach;
|
||||
|
@ -54,19 +56,23 @@ var inIt = false;
|
|||
|
||||
var testBindings;
|
||||
|
||||
/**
|
||||
* Mechanism to run `beforeEach()` functions of Angular tests.
|
||||
*
|
||||
* Note: Jasmine own `beforeEach` is used by this library to handle DI bindings.
|
||||
*/
|
||||
class BeforeEachRunner {
|
||||
_fns: FunctionWithParamTokens[];
|
||||
_parent: BeforeEachRunner;
|
||||
constructor(parent: BeforeEachRunner) {
|
||||
this._fns = [];
|
||||
this._parent = parent;
|
||||
}
|
||||
private _fns: Array<FunctionWithParamTokens | SyncTestFn> = [];
|
||||
|
||||
beforeEach(fn: FunctionWithParamTokens) { this._fns.push(fn); }
|
||||
constructor(private _parent: BeforeEachRunner) {}
|
||||
|
||||
run(injector) {
|
||||
beforeEach(fn: FunctionWithParamTokens | SyncTestFn): void { this._fns.push(fn); }
|
||||
|
||||
run(injector): void {
|
||||
if (this._parent) this._parent.run(injector);
|
||||
this._fns.forEach((fn) => fn.execute(injector));
|
||||
this._fns.forEach((fn) => {
|
||||
return isFunction(fn) ? (<SyncTestFn>fn)() : (<FunctionWithParamTokens>fn).execute(injector);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,17 +100,13 @@ export function xdescribe(...args) {
|
|||
return _describe(jsmXDescribe, ...args);
|
||||
}
|
||||
|
||||
export function beforeEach(fn) {
|
||||
export function beforeEach(fn: FunctionWithParamTokens | SyncTestFn) {
|
||||
if (runnerStack.length > 0) {
|
||||
// Inside a describe block, beforeEach() uses a BeforeEachRunner
|
||||
var runner = runnerStack[runnerStack.length - 1];
|
||||
if (!(fn instanceof FunctionWithParamTokens)) {
|
||||
fn = inject([], fn);
|
||||
}
|
||||
runner.beforeEach(fn);
|
||||
runnerStack[runnerStack.length - 1].beforeEach(fn);
|
||||
} else {
|
||||
// Top level beforeEach() are delegated to jasmine
|
||||
jsmBeforeEach(fn);
|
||||
jsmBeforeEach(<SyncTestFn>fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,34 +130,57 @@ export function beforeEachBindings(fn) {
|
|||
});
|
||||
}
|
||||
|
||||
function _it(jsmFn, name, fn, timeOut) {
|
||||
function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | AnyTestFn,
|
||||
timeOut: number) {
|
||||
var runner = runnerStack[runnerStack.length - 1];
|
||||
|
||||
jsmFn(name, function(done) {
|
||||
var async = false;
|
||||
if (testFn instanceof FunctionWithParamTokens) {
|
||||
// The test case uses inject(). ie `it('test', inject([AsyncTestCompleter], (async) => { ...
|
||||
// }));`
|
||||
|
||||
var completerBinding =
|
||||
bind(AsyncTestCompleter)
|
||||
.toFactory(() => {
|
||||
// Mark the test as async when an AsyncTestCompleter is injected in an it()
|
||||
if (!inIt) throw new Error('AsyncTestCompleter can only be injected in an "it()"');
|
||||
async = true;
|
||||
return new AsyncTestCompleter(done);
|
||||
});
|
||||
if (testFn.hasToken(AsyncTestCompleter)) {
|
||||
jsmFn(name, (done) => {
|
||||
var completerBinding =
|
||||
bind(AsyncTestCompleter)
|
||||
.toFactory(() => {
|
||||
// Mark the test as async when an AsyncTestCompleter is injected in an it()
|
||||
if (!inIt)
|
||||
throw new Error('AsyncTestCompleter can only be injected in an "it()"');
|
||||
return new AsyncTestCompleter(done);
|
||||
});
|
||||
|
||||
var injector = createTestInjector([...testBindings, completerBinding]);
|
||||
runner.run(injector);
|
||||
var injector = createTestInjector([...testBindings, completerBinding]);
|
||||
runner.run(injector);
|
||||
|
||||
if (!(fn instanceof FunctionWithParamTokens)) {
|
||||
fn = inject([], fn);
|
||||
inIt = true;
|
||||
testFn.execute(injector);
|
||||
inIt = false;
|
||||
}, timeOut);
|
||||
} else {
|
||||
jsmFn(name, () => {
|
||||
var injector = createTestInjector(testBindings);
|
||||
runner.run(injector);
|
||||
testFn.execute(injector);
|
||||
}, timeOut);
|
||||
}
|
||||
|
||||
inIt = true;
|
||||
fn.execute(injector);
|
||||
inIt = false;
|
||||
} else {
|
||||
// The test case doesn't use inject(). ie `it('test', (done) => { ... }));`
|
||||
|
||||
if (!async) done();
|
||||
}, timeOut);
|
||||
if ((<any>testFn).length === 0) {
|
||||
jsmFn(name, () => {
|
||||
var injector = createTestInjector(testBindings);
|
||||
runner.run(injector);
|
||||
(<SyncTestFn>testFn)();
|
||||
}, timeOut);
|
||||
} else {
|
||||
jsmFn(name, (done) => {
|
||||
var injector = createTestInjector(testBindings);
|
||||
runner.run(injector);
|
||||
(<AsyncTestFn>testFn)(done);
|
||||
}, timeOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function it(name, fn, timeOut = null) {
|
||||
|
|
Loading…
Reference in New Issue