Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
*/

import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone} from '@angular/core/testing';
import {TestComponentBuilder, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, withProviders} from '@angular/core/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {Injectable, Component, Input, ViewMetadata} from '@angular/core';
import {NgIf} from '@angular/common';
import {TimerWrapper} from '../src/facade/async';
import {IS_DART} from '../src/facade/lang';
import {PromiseWrapper} from '../src/facade/promise';
import {dispatchEvent} from '@angular/platform-browser/testing/browser_util';
import {withProviders} from '@angular/core/testing/test_injector';

@Component(
{selector: 'child-comp', template: `<span>Original {{childBinding}}</span>`, directives: []})
Expand Down
5 changes: 3 additions & 2 deletions modules/@angular/compiler/testing/test_component_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
*/

import {AnimationEntryMetadata, Compiler, ComponentFactory, Inject, Injectable, Injector, NgZone, ViewMetadata} from '@angular/core';
import {ComponentFixture, ComponentFixtureNoNgZone, TestComponentBuilder, TestInjector} from '@angular/core/testing';
import {ComponentFixture, ComponentFixtureNoNgZone, TestBed, TestComponentBuilder} from '@angular/core/testing';

import {DirectiveResolver, ViewResolver} from '../index';
import {MapWrapper} from '../src/facade/collection';
import {ConcreteType, IS_DART, Type, isPresent} from '../src/facade/lang';


/**
* A TestComponentBuilder that allows overriding based on the compiler.
*/
Expand All @@ -31,7 +32,7 @@ export class OverridingTestComponentBuilder extends TestComponentBuilder {
/** @internal */
_viewOverrides = new Map<Type, ViewMetadata>();

constructor(@Inject(TestInjector) injector: Injector) { super(injector); }
constructor(@Inject(TestBed) injector: Injector) { super(injector); }

/** @internal */
_clone(): OverridingTestComponentBuilder {
Expand Down
2 changes: 1 addition & 1 deletion modules/@angular/core/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ export * from './testing/async';
export * from './testing/component_fixture';
export * from './testing/fake_async';
export * from './testing/test_component_builder';
export * from './testing/test_injector';
export * from './testing/test_bed';
export * from './testing/testing';
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ const UNDEFINED = new Object();
/**
* @experimental
*/
export class TestInjector implements Injector {
export class TestBed implements Injector {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you also want to rename the file to test_bed.ts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

private _instantiated: boolean = false;

private _compiler: Compiler = null;
private _moduleRef: AppModuleRef<any> = null;
private _appModuleFactory: AppModuleFactory<any> = null;

private _compilerProviders: Array<Type|Provider|any[]|any> = [];
private _compilerUseJit: boolean = true;
Expand All @@ -36,6 +37,7 @@ export class TestInjector implements Injector {
reset() {
this._compiler = null;
this._moduleRef = null;
this._appModuleFactory = null;
this._compilerProviders = [];
this._compilerUseJit = true;
this._providers = [];
Expand Down Expand Up @@ -89,16 +91,43 @@ export class TestInjector implements Injector {
}
}

createInjectorSync(): Injector {
createAppModuleFactory(): Promise<AppModuleFactory<any>> {
if (this._instantiated) {
return this;
throw new BaseException(
'Cannot run precompilation when the test AppModule has already been instantiated. ' +
'Make sure you are not using `inject` before `doAsyncPrecompilation`.');
}

if (this._appModuleFactory) {
return Promise.resolve(this._appModuleFactory);
}

let moduleMeta = this._createCompilerAndModuleMeta();
return this._createFromModuleFactory(
this._compiler.compileAppModuleSync(_NoopModule, moduleMeta));

return this._compiler.compileAppModuleAsync(_NoopModule, moduleMeta)
.then((appModuleFactory) => {
this._appModuleFactory = appModuleFactory;
return appModuleFactory;
});
}

createInjectorAsync(): Promise<Injector> {
initTestAppModule() {
if (this._instantiated) {
return;
}

if (this._appModuleFactory) {
this._createFromModuleFactory(this._appModuleFactory);
} else {
let moduleMeta = this._createCompilerAndModuleMeta();
this._createFromModuleFactory(this._compiler.compileAppModuleSync(_NoopModule, moduleMeta));
}
}

/**
* @internal
*/
_createInjectorAsync(): Promise<Injector> {
if (this._instantiated) {
return Promise.resolve(this);
}
Expand All @@ -115,7 +144,7 @@ export class TestInjector implements Injector {
deprecatedAppProviders: this._providers
});
const moduleMeta = new AppModuleMetadata({
providers: this._providers.concat([{provide: TestInjector, useValue: this}]),
providers: this._providers.concat([{provide: TestBed, useValue: this}]),
modules: this._modules.concat([this.appModule]),
directives: this._directives,
pipes: this._pipes,
Expand All @@ -134,9 +163,9 @@ export class TestInjector implements Injector {
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND) {
if (!this._instantiated) {
throw new BaseException(
'Illegal state: The TestInjector has not yet been created. Call createInjectorSync/Async first!');
'Illegal state: The test bed\'s injector has not yet been created. Call initTestAppModule first!');
}
if (token === TestInjector) {
if (token === TestBed) {
return this;
}
// Tests can inject things from the app module and from the compiler,
Expand All @@ -148,23 +177,30 @@ export class TestInjector implements Injector {
execute(tokens: any[], fn: Function): any {
if (!this._instantiated) {
throw new BaseException(
'Illegal state: The TestInjector has not yet been created. Call createInjectorSync/Async first!');
'Illegal state: The test bed\'s injector has not yet been created. Call initTestAppModule first!');
}
var params = tokens.map(t => this.get(t));
return FunctionWrapper.apply(fn, params);
}
}

var _testInjector: TestInjector = null;
var _testBed: TestBed = null;

/**
* @experimental
*/
export function getTestInjector() {
if (_testInjector == null) {
_testInjector = new TestInjector();
export function getTestBed() {
if (_testBed == null) {
_testBed = new TestBed();
}
return _testInjector;
return _testBed;
}

/**
* @deprecated use getTestBed instead.
*/
export function getTestInjector() {
return getTestBed();
}

/**
Expand Down Expand Up @@ -208,12 +244,12 @@ export function setBaseTestProviders(
* @experimental
*/
export function initTestEnvironment(appModule: Type, platform: PlatformRef) {
var testInjector = getTestInjector();
if (testInjector.platform || testInjector.appModule) {
var testBed = getTestBed();
if (testBed.platform || testBed.appModule) {
throw new BaseException('Cannot set base providers because it has already been called');
}
testInjector.platform = platform;
testInjector.appModule = appModule;
testBed.platform = platform;
testBed.appModule = appModule;
}

/**
Expand All @@ -231,10 +267,22 @@ export function resetBaseTestProviders() {
* @experimental
*/
export function resetTestEnvironment() {
var testInjector = getTestInjector();
testInjector.platform = null;
testInjector.appModule = null;
testInjector.reset();
var testBed = getTestBed();
testBed.platform = null;
testBed.appModule = null;
testBed.reset();
}

/**
* Run asynchronous precompilation for the test's AppModule. It is necessary to call this function
* if your test is using an AppModule which has precompiled components that require an asynchronous
* call, such as an XHR. Should be called once before the test case.
*
* @experimental
*/
export function doAsyncPrecompilation(): Promise<any> {
let testBed = getTestBed();
return testBed.createAppModuleFactory();
}

/**
Expand Down Expand Up @@ -262,39 +310,31 @@ export function resetTestEnvironment() {
* @stable
*/
export function inject(tokens: any[], fn: Function): () => any {
let testInjector = getTestInjector();
let testBed = getTestBed();
if (tokens.indexOf(AsyncTestCompleter) >= 0) {
return () => {
// Return an async test method that returns a Promise if AsyncTestCompleter is one of the
// injected tokens.
return testInjector.createInjectorAsync().then(() => {
let completer: AsyncTestCompleter = testInjector.get(AsyncTestCompleter);
testInjector.execute(tokens, fn);
return testBed._createInjectorAsync().then(() => {
let completer: AsyncTestCompleter = testBed.get(AsyncTestCompleter);
testBed.execute(tokens, fn);
return completer.promise;
});
};
} else {
return () => {
// Return a asynchronous test method with the injected tokens.
// TODO(tbosch): Right now, we can only detect the AsyncTestZoneSpec via its name.
// (see https://github.com/angular/zone.js/issues/370)
if (Zone.current.name.toLowerCase().indexOf('asynctestzone') >= 0) {
return testInjector.createInjectorAsync().then(() => testInjector.execute(tokens, fn));
} else {
// Return a synchronous test method with the injected tokens.
try {
testInjector.createInjectorSync();
} catch (e) {
if (e instanceof ComponentStillLoadingError) {
throw new Error(
`This test module precompiles the component ${stringify(e.compType)} which is using a "templateUrl", but the test is synchronous. ` +
`Please use the "async(...)" or "fakeAsync(...)" helper functions to make the test asynchronous.`);
} else {
throw e;
}
try {
testBed.initTestAppModule();
} catch (e) {
if (e instanceof ComponentStillLoadingError) {
throw new Error(
`This test module precompiles the component ${stringify(e.compType)} which is using a "templateUrl", but precompilation was never done. ` +
`Please call "doAsyncPrecompilation" before "inject".`);
} else {
throw e;
}
return testInjector.execute(tokens, fn);
}
return testBed.execute(tokens, fn);
};
}
}
Expand All @@ -314,14 +354,14 @@ export class InjectSetupWrapper {
private _addModule() {
var moduleDef = this._moduleDef();
if (moduleDef) {
getTestInjector().configureModule(moduleDef);
getTestBed().configureModule(moduleDef);
}
}

inject(tokens: any[], fn: Function): () => any {
return () => {
this._addModule();
return inject_impl(tokens, fn)();
return inject(tokens, fn)();
};
}
}
Expand All @@ -346,9 +386,4 @@ export function withModule(moduleDef: () => {
return new InjectSetupWrapper(moduleDef);
}


// This is to ensure inject(Async) within InjectSetupWrapper doesn't call itself
// when transpiled to Dart.
var inject_impl = inject;

class _NoopModule {}
12 changes: 6 additions & 6 deletions modules/@angular/core/testing/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@
* allows tests to be asynchronous by either returning a promise or using a 'done' parameter.
*/

import {TestInjector, getTestInjector} from './test_injector';
import {TestBed, getTestBed} from './test_bed';

declare var global: any;

var _global = <any>(typeof window === 'undefined' ? global : window);

var testInjector: TestInjector = getTestInjector();
var testBed: TestBed = getTestBed();

// Reset the test providers before each test.
if (_global.beforeEach) {
_global.beforeEach(() => { testInjector.reset(); });
_global.beforeEach(() => { testBed.reset(); });
}

/**
Expand All @@ -34,7 +34,7 @@ if (_global.beforeEach) {
export function addProviders(providers: Array<any>): void {
if (!providers) return;
try {
testInjector.configureModule({providers: providers});
testBed.configureModule({providers: providers});
} catch (e) {
throw new Error(
'addProviders can\'t be called after the injector has been already created for this test. ' +
Expand All @@ -58,7 +58,7 @@ export function configureModule(moduleDef: {
}): void {
if (!moduleDef) return;
try {
testInjector.configureModule(moduleDef);
testBed.configureModule(moduleDef);
} catch (e) {
throw new Error(
'configureModule can\'t be called after the injector has been already created for this test. ' +
Expand All @@ -76,7 +76,7 @@ export function configureModule(moduleDef: {
export function configureCompiler(config: {providers?: any[], useJit?: boolean}): void {
if (!config) return;
try {
testInjector.configureCompiler(config);
testBed.configureCompiler(config);
} catch (e) {
throw new Error(
'configureCompiler can\'t be called after the injector has been already created for this test. ' +
Expand Down
12 changes: 6 additions & 6 deletions modules/@angular/core/testing/testing_internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {StringMapWrapper} from '../src/facade/collection';
import {Math, global, isFunction, isPromise} from '../src/facade/lang';

import {AsyncTestCompleter} from './async_test_completer';
import {getTestInjector, inject} from './test_injector';
import {getTestBed, inject} from './test_bed';

export {AsyncTestCompleter} from './async_test_completer';
export {MockAnimationPlayer} from './mock_animation_player';
export {inject} from './test_injector';
export {inject} from './test_bed';
export * from './logger';
export * from './ng_zone_mock';
export * from './mock_application_ref';
Expand All @@ -40,7 +40,7 @@ var inIt = false;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 3000;
var globalTimeOut = jasmine.DEFAULT_TIMEOUT_INTERVAL;

var testInjector = getTestInjector();
var testBed = getTestBed();

/**
* Mechanism to run `beforeEach()` functions of Angular tests.
Expand All @@ -61,7 +61,7 @@ class BeforeEachRunner {
}

// Reset the test providers before each test
jsmBeforeEach(() => { testInjector.reset(); });
jsmBeforeEach(() => { testBed.reset(); });

function _describe(jsmFn: any /** TODO #9100 */, ...args: any[] /** TODO #9100 */) {
var parentRunner = runnerStack.length === 0 ? null : runnerStack[runnerStack.length - 1];
Expand Down Expand Up @@ -110,7 +110,7 @@ export function beforeEachProviders(fn: any /** TODO #9100 */): void {
jsmBeforeEach(() => {
var providers = fn();
if (!providers) return;
testInjector.configureModule({providers: providers});
testBed.configureModule({providers: providers});
});
}

Expand Down Expand Up @@ -138,7 +138,7 @@ function _it(jsmFn: Function, name: string, testFn: Function, testTimeOut: numbe
return new AsyncTestCompleter();
}
};
testInjector.configureModule({providers: [completerProvider]});
testBed.configureModule({providers: [completerProvider]});
runner.run();

inIt = true;
Expand Down
Loading