feat(testing): add implicit test module

Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa609f).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to #9726
Closes #9846
This commit is contained in:
Tobias Bosch
2016-07-04 09:37:30 -07:00
parent 37e6da6dfb
commit 8d746e3f67
38 changed files with 1000 additions and 497 deletions

View File

@ -1,7 +1,7 @@
import {LowerCasePipe, NgIf} from '@angular/common';
import {CompilerConfig} from '@angular/compiler';
import {AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
import {ComponentFixture} from '@angular/core/testing';
import {AppModule, AppModuleMetadata, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Host, Inject, Injectable, Injector, OpaqueToken, Optional, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
import {ComponentFixture, configureCompiler} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {BaseException} from '../../src/facade/exceptions';
@ -119,16 +119,13 @@ function declareTests({useJit}: {useJit: boolean}) {
var compiler: Compiler;
var injector: Injector;
beforeEach(() => { configureCompiler({useJit: useJit}); });
beforeEach(inject([Compiler, Injector], (_compiler: Compiler, _injector: Injector) => {
compiler = _compiler;
injector = _injector;
}));
beforeEachProviders(() => [{
provide: CompilerConfig,
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
}]);
describe('precompile', function() {
it('should resolve ComponentFactories', () => {
let appModule = compiler.compileAppModuleSync(ModuleWithPrecompile).create();
@ -206,6 +203,7 @@ function declareTests({useJit}: {useJit: boolean}) {
it('should provide a ComponentResolver instance that uses the directives/pipes of the module',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes).create();
let boundCompiler: ComponentResolver = appModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent(CompUsingModuleDirectiveAndPipe).then((cf) => {
@ -215,6 +213,22 @@ function declareTests({useJit}: {useJit: boolean}) {
});
}));
it('should provide a ComponentResolver instance that delegates to the parent ComponentResolver for strings',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
let parentResolver: any =
jasmine.createSpyObj('resolver', ['resolveComponent', 'clearCache']);
let appModule = compiler.compileAppModuleSync(ModuleWithDirectivesAndPipes)
.create(ReflectiveInjector.resolveAndCreate(
[{provide: ComponentResolver, useValue: parentResolver}]));
parentResolver.resolveComponent.and.returnValue(
Promise.resolve('someFactoryFromParent'));
let boundCompiler: ComponentResolver = appModule.injector.get(ComponentResolver);
boundCompiler.resolveComponent('someString').then((result) => {
expect(parentResolver.resolveComponent).toHaveBeenCalledWith('someString');
expect(result).toBe('someFactoryFromParent');
async.done();
});
}));
});
describe('providers', function() {

View File

@ -7,7 +7,7 @@
*/
import {TestComponentBuilder} from '@angular/compiler/testing';
import {ComponentFixture, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {ComponentFixture, configureCompiler, configureModule, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {isBlank, NumberWrapper, ConcreteType,} from '../../src/facade/lang';
@ -23,14 +23,14 @@ import {IS_DART, Type} from '../../src/facade/lang';
import {EventEmitter, ObservableWrapper} from '../../src/facade/async';
import {Component, DebugElement, Directive, TemplateRef, ChangeDetectorRef, ViewContainerRef, Input, Output, forwardRef, ViewMetadata, Pipe, RootRenderer, Renderer, RenderComponentType, Injectable, provide, OnInit, DoCheck, OnChanges, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked} from '@angular/core';
import {Component, DebugElement, Directive, TemplateRef, ChangeDetectorRef, ViewContainerRef, Input, Output, forwardRef, ViewMetadata, Pipe, RootRenderer, Renderer, RenderComponentType, Injectable, provide, OnInit, DoCheck, OnChanges, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, Injector} from '@angular/core';
import {NgFor, NgIf} from '@angular/common';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {AsyncPipe} from '@angular/common';
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
import {MockSchemaRegistry} from '@angular/compiler/testing';
import {TEST_PROVIDERS} from '@angular/compiler/test/test_bindings';
import {TEST_COMPILER_PROVIDERS} from '@angular/compiler/test/test_bindings';
import {DebugDomRenderer} from '@angular/core/src/debug/debug_renderer';
import {DomRootRenderer} from '@angular/platform-browser/src/dom/dom_renderer';
@ -88,11 +88,13 @@ export function main() {
// On CJS fakeAsync is not supported...
if (!getDOM().supportsDOMEvents()) return;
beforeEachProviders(
() =>
[RenderLog, DirectiveLog, {provide: RootRenderer, useClass: LoggingRootRenderer},
TEST_PROVIDERS,
]);
beforeEach(() => {
configureCompiler({providers: TEST_COMPILER_PROVIDERS});
configureModule({
providers:
[RenderLog, DirectiveLog, {provide: RootRenderer, useClass: LoggingRootRenderer}]
});
});
beforeEach(inject(
[TestComponentBuilder, ElementSchemaRegistry, RenderLog, DirectiveLog],

View File

@ -7,7 +7,7 @@
*/
import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {fakeAsync, tick, ComponentFixture} from '@angular/core/testing';
import {fakeAsync, tick, ComponentFixture, configureCompiler, configureModule} from '@angular/core/testing';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
@ -53,13 +53,10 @@ export function main() {
function declareTests({useJit}: {useJit: boolean}) {
describe('integration tests', function() {
beforeEachProviders(
() =>
[{
provide: CompilerConfig,
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
},
{provide: ANCHOR_ELEMENT, useValue: el('<div></div>')}]);
beforeEach(() => {
configureCompiler({useJit: useJit});
configureModule({providers: [{provide: ANCHOR_ELEMENT, useValue: el('<div></div>')}]});
});
describe('react to record changes', function() {
it('should consume text node changes',
@ -1802,10 +1799,16 @@ function declareTests({useJit}: {useJit: boolean}) {
});
describe('logging property updates', () => {
beforeEachProviders(() => [{
provide: CompilerConfig,
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
}]);
beforeEach(() => {
configureCompiler({
providers: [{
provide: CompilerConfig,
// Note: we are testing the `genDebugInfo` flag here, so we
// need to set it explicitely!
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
}]
});
});
it('should reflect property values as attributes',
inject(

View File

@ -9,14 +9,13 @@
import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {configureCompiler} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {OpaqueToken, ViewMetadata, Component, Directive, AfterContentInit, AfterViewInit, QueryList, ContentChildren, ViewChildren, Input} from '@angular/core';
import {NgIf} from '@angular/common';
import {CompilerConfig} from '@angular/compiler';
import {el} from '@angular/platform-browser/testing/browser_util';
const ANCHOR_ELEMENT = new OpaqueToken('AnchorElement');
export function main() {
describe('jit', () => { declareTests({useJit: true}); });
describe('no jit', () => { declareTests({useJit: false}); });
@ -25,14 +24,7 @@ export function main() {
function declareTests({useJit}: {useJit: boolean}) {
describe('<ng-container>', function() {
beforeEachProviders(
() =>
[{
provide: CompilerConfig,
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
},
{provide: ANCHOR_ELEMENT, useValue: el('<div></div>')},
]);
beforeEach(() => { configureCompiler({useJit: useJit}); });
it('should be rendered as comment with children as siblings',
inject(

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {provide} from '@angular/core';
import {Component, provide} from '@angular/core';
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
import {ComponentResolver, ReflectorComponentResolver} from '@angular/core/src/linker/component_resolver';
import {ReflectionInfo, reflector} from '@angular/core/src/reflection/reflection';
@ -16,34 +16,30 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
export function main() {
describe('Compiler', () => {
var someCompFactory: any /** TODO #9100 */;
var compiler: ComponentResolver;
beforeEachProviders(() => [{provide: ComponentResolver, useClass: ReflectorComponentResolver}]);
beforeEach(inject([ComponentResolver], (_compiler: ComponentResolver) => {
beforeEach(() => {
someCompFactory = new ComponentFactory(null, null, null);
reflector.registerType(SomeComponent, new ReflectionInfo([someCompFactory]));
}));
compiler = new ReflectorComponentResolver();
});
it('should read the template from an annotation',
inject(
[AsyncTestCompleter, ComponentResolver],
(async: AsyncTestCompleter, compiler: ComponentResolver) => {
compiler.resolveComponent(SomeComponent).then((compFactory: ComponentFactory<any>) => {
expect(compFactory).toBe(someCompFactory);
async.done();
return null;
});
}));
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compiler.resolveComponent(SomeComponent).then((compFactory: ComponentFactory<any>) => {
expect(compFactory).toBe(someCompFactory);
async.done();
return null;
});
}));
it('should throw when given a string',
inject(
[AsyncTestCompleter, ComponentResolver],
(async: AsyncTestCompleter, compiler: ComponentResolver) => {
compiler.resolveComponent('someString').catch((e) => {
expect(e.message).toContain('Cannot resolve component using \'someString\'.')
async.done();
});
}));
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
compiler.resolveComponent('someString').catch((e) => {
expect(e.message).toContain('Cannot resolve component using \'someString\'.')
async.done();
});
}));
});
}

View File

@ -7,6 +7,7 @@
*/
import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
import {configureCompiler, configureModule} from '@angular/core/testing';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
@ -31,12 +32,10 @@ function declareTests({useJit}: {useJit: boolean}) {
describe('regressions', () => {
describe('platform pipes', () => {
beforeEachProviders(
() => [{
provide: CompilerConfig,
useValue: new CompilerConfig(
{genDebugInfo: true, useJit: useJit, platformPipes: [PlatformPipe]})
}]);
beforeEach(() => {
configureCompiler({useJit: useJit});
configureModule({pipes: [PlatformPipe]});
});
it('should overwrite them by custom pipes',
inject(

View File

@ -9,6 +9,7 @@
import {ddescribe, describe, expect, inject, beforeEachProviders, beforeEach, afterEach, it,} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {configureCompiler} from '@angular/core/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {provide, Injectable, OpaqueToken} from '@angular/core';
import {CompilerConfig} from '@angular/compiler';
@ -18,8 +19,6 @@ import {el} from '@angular/platform-browser/testing/browser_util';
import {DomSanitizationService} from '@angular/platform-browser/src/security/dom_sanitization_service';
const ANCHOR_ELEMENT = /*@ts2dart_const*/ new OpaqueToken('AnchorElement');
export function main() {
if (IS_DART) {
declareTests({useJit: false});
@ -53,13 +52,7 @@ function itAsync(
function declareTests({useJit}: {useJit: boolean}) {
describe('security integration tests', function() {
beforeEachProviders(
() =>
[{
provide: CompilerConfig,
useValue: new CompilerConfig({genDebugInfo: true, useJit: useJit})
},
{provide: ANCHOR_ELEMENT, useValue: el('<div></div>')}]);
beforeEach(() => { configureCompiler({useJit: useJit}); });
let originalLog: (msg: any) => any;
beforeEach(() => {