X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 101 additions & 93 deletions modules/angular2/src/testing/test_injector.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
import {
APP_ID,
APPLICATION_COMMON_PROVIDERS,
AppViewManager,
PLATFORM_COMMON_PROVIDERS,
DirectiveResolver,
DynamicComponentLoader,
Injector,
NgZone,
Renderer,
Provider,
ViewResolver,
provide
ViewResolver
} from 'angular2/core';
import {
BROWSER_PROVIDERS,
BROWSER_APP_COMMON_PROVIDERS
} from 'angular2/src/platform/browser_common';
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
import {MockAnimationBuilder} from 'angular2/src/mock/animation_builder_mock';

import {ProtoViewFactory} from 'angular2/src/core/linker/proto_view_factory';
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
import {
IterableDiffers,
defaultIterableDiffers,
KeyValueDiffers,
defaultKeyValueDiffers,
ChangeDetectorGenConfig
} from 'angular2/src/core/change_detection/change_detection';
import {ExceptionHandler} from 'angular2/src/facade/exceptions';
import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions';
import {XHR} from 'angular2/src/compiler/xhr';

import {DOM} from 'angular2/src/platform/dom/dom_adapter';
Expand All @@ -38,107 +28,124 @@ import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
import {TestComponentBuilder} from './test_component_builder';

import {
EventManager,
EVENT_MANAGER_PLUGINS,
ELEMENT_PROBE_PROVIDERS
} from 'angular2/platform/common_dom';

import {ListWrapper} from 'angular2/src/facade/collection';
import {FunctionWrapper, Type} from 'angular2/src/facade/lang';

import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/linker/view_pool';
import {AppViewManagerUtils} from 'angular2/src/core/linker/view_manager_utils';

import {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
import {DomRenderer} from 'angular2/src/platform/dom/dom_renderer';
import {DomSharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {SharedStylesHost} from 'angular2/src/platform/dom/shared_styles_host';
import {DomEventsPlugin} from 'angular2/src/platform/dom/events/dom_events';
import {FunctionWrapper, ConcreteType, Type, CONST_EXPR} from 'angular2/src/facade/lang';

import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {Log} from './utils';
import {COMPILER_PROVIDERS} from 'angular2/src/compiler/compiler';
import {DomRenderer_} from "angular2/src/platform/dom/dom_renderer";
import {DynamicComponentLoader_} from "angular2/src/core/linker/dynamic_component_loader";
import {AppViewManager_} from "angular2/src/core/linker/view_manager";

/**
* Returns the root injector providers.
*
* This must be kept in sync with the _rootBindings in application.js
*
* @returns {any[]}
* Default patform providers for testing.
*/
export const TEST_PLATFORM_PROVIDERS: Array<Type | Provider | any[]> =
CONST_EXPR([PLATFORM_COMMON_PROVIDERS]);

/**
* Default application providers for tests in a browser.
*/
function _getRootProviders() {
return [provide(Reflector, {useValue: reflector})];
export const TEST_BROWSER_COMMON_APPLICATION_PROVIDERS: Array<Type | Provider | any[]> =
CONST_EXPR([
BROWSER_APP_COMMON_PROVIDERS,
new Provider(APP_ID, {useValue: 'a'}),
ELEMENT_PROBE_PROVIDERS,
new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
new Provider(ViewResolver, {useClass: MockViewResolver}),
Log,
TestComponentBuilder,
new Provider(NgZone, {useClass: MockNgZone}),
new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
// TODO - this is temporarily here so that Angular's internal web worker tests
// still function. Remove it when we have a way of changing the test
// setup per file.
Serializer
]);

function _getXHRForCurrentDOM(): XHR {
var xhrType = <ConcreteType>DOM.getXHR();
return new xhrType();
}

/**
* Returns the application injector providers.
*
* This must be kept in sync with _injectorBindings() in application.js
*
* @returns {any[]}
* Default application providers for tests in a browser and using the runtime compiler.
*/
function _getAppBindings() {
var appDoc;

// The document is only available in browser environment
try {
appDoc = DOM.defaultDoc();
} catch (e) {
appDoc = null;
export const TEST_BROWSER_APPLICATION_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
TEST_BROWSER_COMMON_APPLICATION_PROVIDERS,
// TODO(juliemr): instead of specifying the DOM here, the test should set it up per platform.
new Provider(XHR, {useFactory: _getXHRForCurrentDOM, deps: []}),
COMPILER_PROVIDERS
]);

export class TestInjector {
private _instantiated: boolean = false;

private _injector: Injector = null;

private _providers: Array<Type | Provider | any[]> = [];

reset() {
this._injector = null;
this._providers = [];
this._instantiated = false;
}

platformProviders: Array<Type | Provider | any[]> = TEST_PLATFORM_PROVIDERS;

applicationProviders: Array<Type | Provider | any[]> = TEST_BROWSER_APPLICATION_PROVIDERS;

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 = Injector.resolveAndCreate(this.platformProviders);
this._injector = rootInjector.resolveAndCreateChild(
ListWrapper.concat(this.applicationProviders, this._providers));
this._instantiated = true;
return this._injector;
}

return [
APPLICATION_COMMON_PROVIDERS,
provide(ChangeDetectorGenConfig, {useValue: new ChangeDetectorGenConfig(true, false, true)}),
provide(DOCUMENT, {useValue: appDoc}),
provide(DomRenderer, {useClass: DomRenderer_}),
provide(Renderer, {useExisting: DomRenderer}),
provide(APP_ID, {useValue: 'a'}),
DomSharedStylesHost,
provide(SharedStylesHost, {useExisting: DomSharedStylesHost}),
AppViewPool,
provide(AppViewManager, {useClass: AppViewManager_}),
AppViewManagerUtils,
Serializer,
ELEMENT_PROBE_PROVIDERS,
provide(APP_VIEW_POOL_CAPACITY, {useValue: 500}),
ProtoViewFactory,
provide(DirectiveResolver, {useClass: MockDirectiveResolver}),
provide(ViewResolver, {useClass: MockViewResolver}),
provide(IterableDiffers, {useValue: defaultIterableDiffers}),
provide(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
Log,
provide(DynamicComponentLoader, {useClass: DynamicComponentLoader_}),
PipeResolver,
provide(ExceptionHandler, {useValue: new ExceptionHandler(DOM)}),
provide(LocationStrategy, {useClass: MockLocationStrategy}),
provide(XHR, {useClass: DOM.getXHR()}),
TestComponentBuilder,
provide(NgZone, {useClass: MockNgZone}),
provide(AnimationBuilder, {useClass: MockAnimationBuilder}),
EventManager,
new Provider(EVENT_MANAGER_PLUGINS, {useClass: DomEventsPlugin, multi: true})
];
execute(fn: FunctionWithParamTokens): any {
if (!this._instantiated) {
this.createInjector();
}
return fn.execute(this._injector);
}
}

function _runtimeCompilerBindings() {
return [
provide(XHR, {useClass: DOM.getXHR()}),
COMPILER_PROVIDERS,
];
var _testInjector: TestInjector = null;

export function getTestInjector() {
if (_testInjector == null) {
_testInjector = new TestInjector();
}
return _testInjector;
}

/**
* @deprecated Use TestInjector#createInjector() instead.
*/
export function createTestInjector(providers: Array<Type | Provider | any[]>): Injector {
var rootInjector = Injector.resolveAndCreate(_getRootProviders());
return rootInjector.resolveAndCreateChild(ListWrapper.concat(_getAppBindings(), providers));
var rootInjector = Injector.resolveAndCreate(TEST_PLATFORM_PROVIDERS);
return rootInjector.resolveAndCreateChild(
ListWrapper.concat(TEST_BROWSER_COMMON_APPLICATION_PROVIDERS, providers));
}

/**
* @deprecated Use TestInjector#createInjector() instead.
*/
export function createTestInjectorWithRuntimeCompiler(
providers: Array<Type | Provider | any[]>): Injector {
return createTestInjector(ListWrapper.concat(_runtimeCompilerBindings(), providers));
var rootInjector = Injector.resolveAndCreate(TEST_PLATFORM_PROVIDERS);
return rootInjector.resolveAndCreateChild(
ListWrapper.concat(TEST_BROWSER_APPLICATION_PROVIDERS, providers));
}

/**
Expand All @@ -159,7 +166,8 @@ export function createTestInjectorWithRuntimeCompiler(
* ```
*
* Notes:
* - inject is currently a function because of some Traceur limitation the syntax should eventually
* - inject is currently a function because of some Traceur limitation the syntax should
* eventually
* becomes `it('...', @Inject (object: AClass, async: AsyncTestCompleter) => { ... });`
*
* @param {Array} tokens
Expand Down
30 changes: 11 additions & 19 deletions modules/angular2/src/testing/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {ListWrapper} from 'angular2/src/facade/collection';
import {bind} from 'angular2/core';

import {
createTestInjectorWithRuntimeCompiler,
FunctionWithParamTokens,
inject,
injectAsync
injectAsync,
TestInjector,
getTestInjector
} from './test_injector';

export {inject, injectAsync} from './test_injector';
Expand Down Expand Up @@ -92,14 +93,10 @@ var jsmIt = _global.it;
var jsmIIt = _global.fit;
var jsmXIt = _global.xit;

var testProviders;
var injector;
var testInjector: TestInjector = getTestInjector();

// Reset the test providers before each test.
jsmBeforeEach(() => {
testProviders = [];
injector = null;
});
jsmBeforeEach(() => { testInjector.reset(); });

/**
* Allows overriding default providers of the test injector,
Expand All @@ -115,8 +112,9 @@ export function beforeEachProviders(fn): void {
jsmBeforeEach(() => {
var providers = fn();
if (!providers) return;
testProviders = [...testProviders, ...providers];
if (injector !== null) {
try {
testInjector.addProviders(providers);
} catch (e) {
throw new Error('beforeEachProviders was called after the injector had ' +
'been used in a beforeEach or it block. This invalidates the ' +
'test injector');
Expand Down Expand Up @@ -188,17 +186,13 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An

if (testFn instanceof FunctionWithParamTokens) {
jsmFn(name, (done) => {
if (!injector) {
injector = createTestInjectorWithRuntimeCompiler(testProviders);
}

var finishCallback = () => {
// Wait one more event loop to make sure we catch unreturned promises and
// promise rejections.
setTimeout(done, 0);
};
var returnedTestValue =
runInTestZone(() => testFn.execute(injector), finishCallback, done.fail);
runInTestZone(() => testInjector.execute(testFn), finishCallback, done.fail);

if (testFn.isAsync) {
if (_isPromiseLike(returnedTestValue)) {
Expand Down Expand Up @@ -243,11 +237,9 @@ export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void {
// promise rejections.
setTimeout(done, 0);
};
if (!injector) {
injector = createTestInjectorWithRuntimeCompiler(testProviders);
}

var returnedTestValue = runInTestZone(() => fn.execute(injector), finishCallback, done.fail);
var returnedTestValue =
runInTestZone(() => testInjector.execute(fn), finishCallback, done.fail);
if (fn.isAsync) {
if (_isPromiseLike(returnedTestValue)) {
(<Promise<any>>returnedTestValue).then(null, (err) => { done.fail(err); });
Expand Down
Loading
X Tutup