UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

200 lines (176 loc) 5.84 kB
import {ReflectiveInjector, Provider, PLATFORM_INITIALIZER} from 'angular2/core'; import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions'; import {ListWrapper} from 'angular2/src/facade/collection'; import {FunctionWrapper, isPresent, Type} from 'angular2/src/facade/lang'; import {async} from './async'; import {AsyncTestCompleter} from './async_test_completer'; export {async} from './async'; export class TestInjector { private _instantiated: boolean = false; private _injector: ReflectiveInjector = null; private _providers: Array<Type | Provider | any[]> = []; reset() { this._injector = null; this._providers = []; this._instantiated = false; } platformProviders: Array<Type | Provider | any[]> = []; applicationProviders: Array<Type | Provider | any[]> = []; addProviders(providers: Array<Type | Provider | any[]>) { if (this._instantiated) { throw new BaseException('Cannot add providers after test injector is instantiated'); } this._providers = ListWrapper.concat(this._providers, providers); } createInjector() { var rootInjector = ReflectiveInjector.resolveAndCreate(this.platformProviders); this._injector = rootInjector.resolveAndCreateChild( ListWrapper.concat(this.applicationProviders, this._providers)); this._instantiated = true; return this._injector; } get(token: any) { if (!this._instantiated) { this.createInjector(); } return this._injector.get(token); } execute(tokens: any[], fn: Function): any { if (!this._instantiated) { this.createInjector(); } var params = tokens.map(t => this._injector.get(t)); return FunctionWrapper.apply(fn, params); } } var _testInjector: TestInjector = null; export function getTestInjector() { if (_testInjector == null) { _testInjector = new TestInjector(); } return _testInjector; } /** * Set the providers that the test injector should use. These should be providers * common to every test in the suite. * * This may only be called once, to set up the common providers for the current test * suite on teh current platform. If you absolutely need to change the providers, * first use `resetBaseTestProviders`. * * Test Providers for individual platforms are available from * 'angular2/platform/testing/<platform_name>'. */ export function setBaseTestProviders(platformProviders: Array<Type | Provider | any[]>, applicationProviders: Array<Type | Provider | any[]>) { var testInjector = getTestInjector(); if (testInjector.platformProviders.length > 0 || testInjector.applicationProviders.length > 0) { throw new BaseException('Cannot set base providers because it has already been called'); } testInjector.platformProviders = platformProviders; testInjector.applicationProviders = applicationProviders; var injector = testInjector.createInjector(); let inits: Function[] = injector.get(PLATFORM_INITIALIZER, null); if (isPresent(inits)) { inits.forEach(init => init()); } testInjector.reset(); } /** * Reset the providers for the test injector. */ export function resetBaseTestProviders() { var testInjector = getTestInjector(); testInjector.platformProviders = []; testInjector.applicationProviders = []; testInjector.reset(); } /** * Allows injecting dependencies in `beforeEach()` and `it()`. * * Example: * * ``` * beforeEach(inject([Dependency, AClass], (dep, object) => { * // some code that uses `dep` and `object` * // ... * })); * * it('...', inject([AClass], (object) => { * object.doSomething(); * expect(...); * }) * ``` * * Notes: * - inject is currently a function because of some Traceur limitation the syntax should * eventually * becomes `it('...', @Inject (object: AClass, async: AsyncTestCompleter) => { ... });` * * @param {Array} tokens * @param {Function} fn * @return {Function} */ export function inject(tokens: any[], fn: Function): Function { let testInjector = getTestInjector(); if (tokens.indexOf(AsyncTestCompleter) >= 0) { // Return an async test method that returns a Promise if AsyncTestCompleter is one of the // injected tokens. return () => { let completer: AsyncTestCompleter = testInjector.get(AsyncTestCompleter); testInjector.execute(tokens, fn); return completer.promise; } } else { // Return a synchronous test method with the injected tokens. return () => { return getTestInjector().execute(tokens, fn); }; } } export class InjectSetupWrapper { constructor(private _providers: () => any) {} private _addProviders() { var additionalProviders = this._providers(); if (additionalProviders.length > 0) { getTestInjector().addProviders(additionalProviders); } } inject(tokens: any[], fn: Function): Function { return () => { this._addProviders(); return inject(tokens, fn)(); } } /** @Deprecated {use async(withProviders().inject())} */ injectAsync(tokens: any[], fn: Function): Function { return () => { this._addProviders(); return injectAsync(tokens, fn)(); } } } export function withProviders(providers: () => any) { return new InjectSetupWrapper(providers); } /** * @Deprecated {use async(inject())} * * Allows injecting dependencies in `beforeEach()` and `it()`. The test must return * a promise which will resolve when all asynchronous activity is complete. * * Example: * * ``` * it('...', injectAsync([AClass], (object) => { * return object.doSomething().then(() => { * expect(...); * }); * }) * ``` * * @param {Array} tokens * @param {Function} fn * @return {Function} */ export function injectAsync(tokens: any[], fn: Function): Function { return async(inject(tokens, fn)); }