refactor(testing): introduce new testing api to support ng modules

BREAKING CHANGE:
- deprecations:
  * `withProviders`, use `TestBed.withModule` instead
  * `addProviders`, use `TestBed.configureTestingModule` instead
  * `TestComponentBuilder`, use `TestBed.configureTestModule` / `TestBed.override...` / `TestBed.createComponent` instead.

Closes #10354
This commit is contained in:
Tobias Bosch
2016-07-28 04:54:49 -07:00
parent acc6c8d0b7
commit d0a95e35af
45 changed files with 1090 additions and 501 deletions

View File

@ -12,7 +12,7 @@ import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
import {XHR} from '@angular/compiler/src/xhr';
import {MockXHR} from '@angular/compiler/testing/xhr_mock';
import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {configureCompiler} from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {SpyXHR} from './spies';
@ -23,7 +23,7 @@ export function main() {
var dirType: CompileTypeMetadata;
var dirTypeWithHttpUrl: CompileTypeMetadata;
beforeEach(() => { configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
beforeEach(() => { TestBed.configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
beforeEach(() => {
dirType = new CompileTypeMetadata({moduleUrl: 'package:some/module/a.js', name: 'SomeComp'});
@ -179,7 +179,8 @@ export function main() {
describe('normalizeExternalStylesheets', () => {
beforeEach(() => { configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
beforeEach(
() => { TestBed.configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
it('should load an external stylesheet',
inject(

View File

@ -27,7 +27,7 @@ export function main() {
expect(ngModule.selector).toEqual('cmp');
});
it('should allow overriding the @NgModule', () => {
it('should allow overriding the @Directive', () => {
dirResolver.setDirective(
SomeComponent, new ComponentMetadata({selector: 'someOtherSelector'}));
var metadata = dirResolver.resolve(SomeComponent);

View File

@ -0,0 +1,116 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {expect} from '@angular/platform-browser/testing/matchers';
import {MetadataOverrider} from '../testing/metadata_overrider';
interface SomeMetadataType {
plainProp?: string;
getterProp?: string;
arrayProp?: any[];
}
class SomeMetadata implements SomeMetadataType {
plainProp: string;
private _getterProp: string;
get getterProp(): string { return this._getterProp; }
arrayProp: any[];
constructor(options: SomeMetadataType) {
this.plainProp = options.plainProp;
this._getterProp = options.getterProp;
this.arrayProp = options.arrayProp;
}
}
export function main() {
describe('metadata overrider', () => {
let overrider: MetadataOverrider;
beforeEach(() => { overrider = new MetadataOverrider(); });
it('should return a new instance with the same values', () => {
const oldInstance = new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someInput'});
const newInstance = overrider.overrideMetadata(SomeMetadata, oldInstance, {});
expect(newInstance).not.toBe(oldInstance);
expect(newInstance).toBeAnInstanceOf(SomeMetadata);
expect(newInstance).toEqual(oldInstance);
});
it('should set individual properties and keep others', () => {
const oldInstance =
new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someGetterProp'});
const newInstance =
overrider.overrideMetadata(SomeMetadata, oldInstance, {set: {plainProp: 'newPlainProp'}});
expect(newInstance)
.toEqual(new SomeMetadata({plainProp: 'newPlainProp', getterProp: 'someGetterProp'}));
});
describe('add properties', () => {
it('should replace non array values', () => {
const oldInstance =
new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someGetterProp'});
const newInstance = overrider.overrideMetadata(
SomeMetadata, oldInstance, {add: {plainProp: 'newPlainProp'}});
expect(newInstance)
.toEqual(new SomeMetadata({plainProp: 'newPlainProp', getterProp: 'someGetterProp'}));
});
it('should add to array values', () => {
const oldInstance = new SomeMetadata({arrayProp: ['a']});
const newInstance =
overrider.overrideMetadata(SomeMetadata, oldInstance, {add: {arrayProp: ['b']}});
expect(newInstance).toEqual(new SomeMetadata({arrayProp: ['a', 'b']}));
});
});
describe('remove', () => {
it('should set values to undefined if their value matches', () => {
const oldInstance =
new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someGetterProp'});
const newInstance = overrider.overrideMetadata(
SomeMetadata, oldInstance, {remove: {plainProp: 'somePlainProp'}});
expect(newInstance)
.toEqual(new SomeMetadata({plainProp: undefined, getterProp: 'someGetterProp'}));
});
it('should leave values if their value does not match', () => {
const oldInstance =
new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someGetterProp'});
const newInstance = overrider.overrideMetadata(
SomeMetadata, oldInstance, {remove: {plainProp: 'newPlainProp'}});
expect(newInstance)
.toEqual(new SomeMetadata({plainProp: 'somePlainProp', getterProp: 'someGetterProp'}));
});
it('should remove a value from an array', () => {
const oldInstance =
new SomeMetadata({arrayProp: ['a', 'b', 'c'], getterProp: 'someGetterProp'});
const newInstance = overrider.overrideMetadata(
SomeMetadata, oldInstance, {remove: {arrayProp: ['a', 'c']}});
expect(newInstance)
.toEqual(new SomeMetadata({arrayProp: ['b'], getterProp: 'someGetterProp'}));
});
it('should support types as values', () => {
class Class1 {}
class Class2 {}
class Class3 {}
const instance1 = new SomeMetadata({arrayProp: [Class1, Class2, Class3]});
const instance2 =
overrider.overrideMetadata(SomeMetadata, instance1, {remove: {arrayProp: [Class1]}});
expect(instance2).toEqual(new SomeMetadata({arrayProp: [Class2, Class3]}));
const instance3 =
overrider.overrideMetadata(SomeMetadata, instance2, {remove: {arrayProp: [Class3]}});
expect(instance3).toEqual(new SomeMetadata({arrayProp: [Class2]}));
});
});
});
}

View File

@ -9,7 +9,7 @@
import {CompilerConfig} from '@angular/compiler/src/config';
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, Component, Directive, DoCheck, Injectable, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation} from '@angular/core';
import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks';
import {configureCompiler} from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {CompileNgModuleMetadata} from '../src/compile_metadata';
@ -21,7 +21,7 @@ import {TEST_COMPILER_PROVIDERS} from './test_bindings';
export function main() {
describe('CompileMetadataResolver', () => {
beforeEach(() => { configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
beforeEach(() => { TestBed.configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
describe('getDirectiveMetadata', () => {
it('should read metadata',

View File

@ -10,7 +10,7 @@ import {beforeEach, ddescribe, xdescribe, describe, iit, inject, beforeEachProvi
import {expect} from '@angular/platform-browser/testing/matchers';
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
import {ConcreteType, stringify} from '../src/facade/lang';
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, TestBed} from '@angular/core/testing';
import {XHR, DirectiveResolver} from '@angular/compiler';
import {MockDirectiveResolver} from '@angular/compiler/testing';
@ -36,7 +36,8 @@ export function main() {
let dirResolver: MockDirectiveResolver;
let injector: Injector;
beforeEach(() => { configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
beforeEach(
() => { TestBed.configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
beforeEach(inject(
[Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector],

View File

@ -14,7 +14,7 @@ import {TEMPLATE_TRANSFORMS, TemplateParser, splitClasses} from '@angular/compil
import {MockSchemaRegistry} from '@angular/compiler/testing';
import {SchemaMetadata, SecurityContext} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {configureCompiler} from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Identifiers, identifierToken} from '../src/identifiers';
@ -40,7 +40,7 @@ export function main() {
function commonBeforeEach() {
beforeEach(() => {
console = new ArrayConsole();
configureCompiler({providers: [{provide: Console, useValue: console}]});
TestBed.configureCompiler({providers: [{provide: Console, useValue: console}]});
});
beforeEach(inject([TemplateParser], (parser: TemplateParser) => {
var component = CompileDirectiveMetadata.create({
@ -66,10 +66,10 @@ export function main() {
}
describe('TemplateParser template transform', () => {
beforeEach(() => { configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
beforeEach(() => { TestBed.configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
beforeEach(() => {
configureCompiler({
TestBed.configureCompiler({
providers:
[{provide: TEMPLATE_TRANSFORMS, useValue: new FooAstTransformer(), multi: true}]
});
@ -84,7 +84,7 @@ export function main() {
describe('multiple', () => {
beforeEach(() => {
configureCompiler({
TestBed.configureCompiler({
providers:
[{provide: TEMPLATE_TRANSFORMS, useValue: new BarAstTransformer(), multi: true}]
});
@ -101,7 +101,7 @@ export function main() {
// Semi-integration test to make sure TemplateParser properly sets the security context.
// Uses the actual DomElementSchemaRegistry.
beforeEach(() => {
configureCompiler({
TestBed.configureCompiler({
providers: [
TEST_COMPILER_PROVIDERS,
{provide: ElementSchemaRegistry, useClass: DomElementSchemaRegistry}
@ -138,7 +138,7 @@ export function main() {
describe('TemplateParser', () => {
beforeEach(() => {
configureCompiler({providers: [TEST_COMPILER_PROVIDERS, MOCK_SCHEMA_REGISTRY]});
TestBed.configureCompiler({providers: [TEST_COMPILER_PROVIDERS, MOCK_SCHEMA_REGISTRY]});
});
commonBeforeEach();

View File

@ -327,27 +327,6 @@ export function main() {
expect(componentFixture.nativeElement).toHaveText('Mock');
}));
it('should create components synchronously with a custom module',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
@Pipe({name: 'somePipe'})
class SomePipe {
transform(value: any) { return `transformed ${value}`; }
}
@NgModule({declarations: [SomePipe]})
class SomeModule {
}
@Component({selector: 'comp', template: `{{'hello' | somePipe}}`})
class SomeComponent {
}
let componentFixture = tcb.createSync(SomeComponent, SomeModule);
componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('transformed hello');
}));
describe('ComponentFixture', () => {
it('should auto detect changes if autoDetectChanges is called',
inject(