diff --git a/src/components/dialog/dialog.spec.ts b/src/components/dialog/dialog.spec.ts index 75f9f08aa759..9e2bb2131907 100644 --- a/src/components/dialog/dialog.spec.ts +++ b/src/components/dialog/dialog.spec.ts @@ -1,23 +1,11 @@ -import { - inject, - fakeAsync, - async, - ComponentFixture, - TestBed, -} from '@angular/core/testing'; -import { - Component, - Directive, - ViewChild, - ViewContainerRef, -} from '@angular/core'; +import {inject, fakeAsync, async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {NgModule, Component, Directive, ViewChild, ViewContainerRef} from '@angular/core'; import {MdDialog, MdDialogModule} from './dialog'; import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container'; import {MdDialogConfig} from './dialog-config'; import {MdDialogRef} from './dialog-ref'; - describe('MdDialog', () => { let dialog: MdDialog; let overlayContainerElement: HTMLElement; @@ -27,8 +15,7 @@ describe('MdDialog', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [MdDialogModule], - declarations: [PizzaMsg, ComponentWithChildViewContainer, DirectiveWithViewContainer], + imports: [MdDialogModule, DialogTestModule], providers: [ {provide: OverlayContainer, useFactory: () => { overlayContainerElement = document.createElement('div'); @@ -144,3 +131,13 @@ class PizzaMsg { constructor(public dialogRef: MdDialogRef) { } } +// Create a real (non-test) NgModule as a workaround for +// https://github.com/angular/angular/issues/10760 +const TEST_DIRECTIVES = [ComponentWithChildViewContainer, PizzaMsg, DirectiveWithViewContainer]; +@NgModule({ + imports: [MdDialogModule], + exports: TEST_DIRECTIVES, + declarations: TEST_DIRECTIVES, + entryComponents: [ComponentWithChildViewContainer, PizzaMsg], +}) +class DialogTestModule { } diff --git a/src/core/overlay/overlay-directives.spec.ts b/src/core/overlay/overlay-directives.spec.ts index 302701669862..bda8845416ee 100644 --- a/src/core/overlay/overlay-directives.spec.ts +++ b/src/core/overlay/overlay-directives.spec.ts @@ -1,13 +1,4 @@ -import { - inject, - async, - fakeAsync, - flushMicrotasks, - addProviders, - TestComponentBuilder, - ComponentFixture, - TestBed, -} from '@angular/core/testing'; +import {async, fakeAsync, flushMicrotasks, ComponentFixture, TestBed} from '@angular/core/testing'; import {Component, ViewChild} from '@angular/core'; import {ConnectedOverlayDirective, OverlayModule} from './overlay-directives'; import {OverlayContainer} from './overlay-container'; @@ -15,7 +6,6 @@ import {ConnectedPositionStrategy} from './position/connected-position-strategy' describe('Overlay directives', () => { - let builder: TestComponentBuilder; let overlayContainerElement: HTMLElement; let fixture: ComponentFixture; @@ -23,25 +13,18 @@ describe('Overlay directives', () => { TestBed.configureTestingModule({ imports: [OverlayModule], declarations: [ConnectedOverlayDirectiveTest], + providers: [ + {provide: OverlayContainer, useFactory: () => { + overlayContainerElement = document.createElement('div'); + return {getContainerElement: () => overlayContainerElement}; + }} + ], }); - - addProviders([ - {provide: OverlayContainer, useFactory: () => { - overlayContainerElement = document.createElement('div'); - return {getContainerElement: () => overlayContainerElement}; - }} - ]); - })); - - beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - builder = tcb; })); beforeEach(async(() => { - builder.createAsync(ConnectedOverlayDirectiveTest).then(f => { - fixture = f; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(ConnectedOverlayDirectiveTest); + fixture.detectChanges(); })); it(`should create an overlay and attach the directive's template`, () => { diff --git a/src/core/overlay/overlay.spec.ts b/src/core/overlay/overlay.spec.ts index 852c0e441804..961289f342fd 100644 --- a/src/core/overlay/overlay.spec.ts +++ b/src/core/overlay/overlay.spec.ts @@ -1,12 +1,5 @@ -import { - inject, - fakeAsync, - flushMicrotasks, - TestComponentBuilder, - TestBed, - async, -} from '@angular/core/testing'; -import {Component, ViewChild, ViewContainerRef} from '@angular/core'; +import {inject, fakeAsync, flushMicrotasks, TestBed, async} from '@angular/core/testing'; +import {NgModule, Component, ViewChild, ViewContainerRef} from '@angular/core'; import {TemplatePortalDirective, PortalModule} from '../portal/portal-directives'; import {TemplatePortal, ComponentPortal} from '../portal/portal'; import {Overlay} from './overlay'; @@ -18,7 +11,6 @@ import {OverlayModule} from './overlay-directives'; describe('Overlay', () => { - let builder: TestComponentBuilder; let overlay: Overlay; let componentPortal: ComponentPortal; let templatePortal: TemplatePortal; @@ -26,8 +18,7 @@ describe('Overlay', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [OverlayModule, PortalModule], - declarations: [TestComponentWithTemplatePortals, PizzaMsg], + imports: [OverlayModule, PortalModule, OverlayTestModule], providers: [ {provide: OverlayContainer, useFactory: () => { overlayContainerElement = document.createElement('div'); @@ -35,19 +26,17 @@ describe('Overlay', () => { }} ] }); - })); + TestBed.compileComponents(); + })); - let deps = [TestComponentBuilder, Overlay]; - beforeEach(fakeAsync(inject(deps, (tcb: TestComponentBuilder, o: Overlay) => { - builder = tcb; + beforeEach(fakeAsync(inject([Overlay], (o: Overlay) => { overlay = o; - builder.createAsync(TestComponentWithTemplatePortals).then(fixture => { - fixture.detectChanges(); - templatePortal = fixture.componentInstance.templatePortal; - componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef); - }); + let fixture = TestBed.createComponent(TestComponentWithTemplatePortals); + fixture.detectChanges(); + templatePortal = fixture.componentInstance.templatePortal; + componentPortal = new ComponentPortal(PizzaMsg, fixture.componentInstance.viewContainerRef); flushMicrotasks(); }))); @@ -140,24 +129,29 @@ describe('Overlay', () => { /** Simple component for testing ComponentPortal. */ -@Component({ - selector: 'pizza-msg', - template: '

Pizza

', -}) +@Component({template: '

Pizza

'}) class PizzaMsg { } /** Test-bed component that contains a TempatePortal and an ElementRef. */ -@Component({ - selector: 'portal-test', - template: ``, -}) +@Component({template: ``}) class TestComponentWithTemplatePortals { @ViewChild(TemplatePortalDirective) templatePortal: TemplatePortalDirective; constructor(public viewContainerRef: ViewContainerRef) { } } +// Create a real (non-test) NgModule as a workaround for +// https://github.com/angular/angular/issues/10760 +const TEST_COMPONENTS = [PizzaMsg, TestComponentWithTemplatePortals]; +@NgModule({ + imports: [OverlayModule, PortalModule], + exports: TEST_COMPONENTS, + declarations: TEST_COMPONENTS, + entryComponents: TEST_COMPONENTS, +}) +class OverlayTestModule { } + class FakePositionStrategy implements PositionStrategy { apply(element: Element): Promise { element.classList.add('fake-positioned'); diff --git a/src/core/overlay/overlay.ts b/src/core/overlay/overlay.ts index b662a9317204..692d283bdc3c 100644 --- a/src/core/overlay/overlay.ts +++ b/src/core/overlay/overlay.ts @@ -1,5 +1,5 @@ import { - ComponentResolver, + ComponentFactoryResolver, Injectable, } from '@angular/core'; import {OverlayState} from './overlay-state'; @@ -28,7 +28,7 @@ let defaultState = new OverlayState(); @Injectable() export class Overlay { constructor(private _overlayContainer: OverlayContainer, - private _componentResolver: ComponentResolver, + private _componentFactoryResolver: ComponentFactoryResolver, private _positionBuilder: OverlayPositionBuilder) {} /** @@ -68,7 +68,7 @@ export class Overlay { * @returns A portal host for the given DOM element. */ private _createPortalHost(pane: HTMLElement): DomPortalHost { - return new DomPortalHost(pane, this._componentResolver); + return new DomPortalHost(pane, this._componentFactoryResolver); } /** diff --git a/src/core/portal/dom-portal-host.ts b/src/core/portal/dom-portal-host.ts index 2e9a3d8bd478..a4606cec7af9 100644 --- a/src/core/portal/dom-portal-host.ts +++ b/src/core/portal/dom-portal-host.ts @@ -1,4 +1,4 @@ -import {ComponentResolver, ComponentRef, EmbeddedViewRef} from '@angular/core'; +import {ComponentFactoryResolver, ComponentRef, EmbeddedViewRef} from '@angular/core'; import {BasePortalHost, ComponentPortal, TemplatePortal} from './portal'; import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors'; @@ -12,27 +12,27 @@ import {MdComponentPortalAttachedToDomWithoutOriginError} from './portal-errors' export class DomPortalHost extends BasePortalHost { constructor( private _hostDomElement: Element, - private _componentResolver: ComponentResolver) { + private _componentFactoryResolver: ComponentFactoryResolver) { super(); } - /** Attach the given ComponentPortal to DOM element using the ComponentResolver. */ + /** Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. */ attachComponentPortal(portal: ComponentPortal): Promise> { if (portal.viewContainerRef == null) { throw new MdComponentPortalAttachedToDomWithoutOriginError(); } - return this._componentResolver.resolveComponent(portal.component).then(componentFactory => { - let ref = portal.viewContainerRef.createComponent( - componentFactory, - portal.viewContainerRef.length, - portal.injector || portal.viewContainerRef.parentInjector); - - let hostView = > ref.hostView; - this._hostDomElement.appendChild(hostView.rootNodes[0]); - this.setDisposeFn(() => ref.destroy()); - return ref; - }); + let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component); + let ref = portal.viewContainerRef.createComponent( + componentFactory, + portal.viewContainerRef.length, + portal.injector || portal.viewContainerRef.parentInjector); + + let hostView = > ref.hostView; + this._hostDomElement.appendChild(hostView.rootNodes[0]); + this.setDisposeFn(() => ref.destroy()); + + return Promise.resolve(ref); } attachTemplatePortal(portal: TemplatePortal): Promise> { diff --git a/src/core/portal/portal-directives.ts b/src/core/portal/portal-directives.ts index 90fa13afa4e9..eb6e45cfafe2 100644 --- a/src/core/portal/portal-directives.ts +++ b/src/core/portal/portal-directives.ts @@ -3,13 +3,12 @@ import { ComponentRef, Directive, TemplateRef, - ComponentResolver, + ComponentFactoryResolver, ViewContainerRef } from '@angular/core'; import {Portal, TemplatePortal, ComponentPortal, BasePortalHost} from './portal'; - /** * Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal, * the directive instance itself can be attached to a host, enabling declarative use of portals. @@ -46,7 +45,7 @@ export class PortalHostDirective extends BasePortalHost { private _portal: Portal; constructor( - private _componentResolver: ComponentResolver, + private _componentFactoryResolver: ComponentFactoryResolver, private _viewContainerRef: ViewContainerRef) { super(); } @@ -59,7 +58,7 @@ export class PortalHostDirective extends BasePortalHost { this._replaceAttachedPortal(p); } - /** Attach the given ComponentPortal to this PortlHost using the ComponentResolver. */ + /** Attach the given ComponentPortal to this PortlHost using the ComponentFactoryResolver. */ attachComponentPortal(portal: ComponentPortal): Promise> { portal.setAttachedHost(this); @@ -69,14 +68,14 @@ export class PortalHostDirective extends BasePortalHost { portal.viewContainerRef : this._viewContainerRef; - return this._componentResolver.resolveComponent(portal.component).then(componentFactory => { - let ref = viewContainerRef.createComponent( - componentFactory, viewContainerRef.length, - portal.injector || viewContainerRef.parentInjector); + let componentFactory = + this._componentFactoryResolver.resolveComponentFactory(portal.component); + let ref = viewContainerRef.createComponent( + componentFactory, viewContainerRef.length, + portal.injector || viewContainerRef.parentInjector); - this.setDisposeFn(() => ref.destroy()); - return ref; - }); + this.setDisposeFn(() => ref.destroy()); + return Promise.resolve(ref); } /** Attach the given TemplatePortal to this PortlHost as an embedded View. */ diff --git a/src/core/portal/portal.spec.ts b/src/core/portal/portal.spec.ts index 0409c8c527af..e8f0e919f3e3 100644 --- a/src/core/portal/portal.spec.ts +++ b/src/core/portal/portal.spec.ts @@ -2,17 +2,17 @@ import { inject, fakeAsync, flushMicrotasks, - TestComponentBuilder, ComponentFixture, TestBed, async, } from '@angular/core/testing'; import { + NgModule, Component, ViewChildren, QueryList, ViewContainerRef, - ComponentResolver, + ComponentFactoryResolver, Optional, Injector, } from '@angular/core'; @@ -22,192 +22,140 @@ import {DomPortalHost} from './dom-portal-host'; describe('Portals', () => { - let builder: TestComponentBuilder; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [PortalModule], - declarations: [PortalTestApp, ArbitraryViewContainerRefComponent, PizzaMsg], + imports: [PortalModule, PortalTestModule], }); - })); - beforeEach(fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - builder = tcb; - }))); + TestBed.compileComponents(); + })); describe('PortalHostDirective', () => { - it('should load a component into the portal', fakeAsync(() => { - let appFixture: ComponentFixture; - - builder.createAsync(PortalTestApp).then(fixture => { - appFixture = fixture; - }); + let fixture: ComponentFixture; - // Flush the async creation of the PortalTestApp. - flushMicrotasks(); + beforeEach(fakeAsync(() => { + fixture = TestBed.createComponent(PortalTestApp); + })); + it('should load a component into the portal', fakeAsync(() => { // Set the selectedHost to be a ComponentPortal. - let testAppComponent = appFixture.debugElement.componentInstance; + let testAppComponent = fixture.debugElement.componentInstance; testAppComponent.selectedPortal = new ComponentPortal(PizzaMsg); - appFixture.detectChanges(); + fixture.detectChanges(); // Flush the attachment of the Portal. flushMicrotasks(); // Expect that the content of the attached portal is present. - let hostContainer = appFixture.nativeElement.querySelector('.portal-container'); + let hostContainer = fixture.nativeElement.querySelector('.portal-container'); expect(hostContainer.textContent).toContain('Pizza'); })); it('should load a component into the portal with a given injector', fakeAsync(() => { - let appFixture: ComponentFixture; - - builder.createAsync(PortalTestApp).then(fixture => { - appFixture = fixture; - }); - - // Flush the async creation of the PortalTestApp. - flushMicrotasks(); - // Create a custom injector for the component. - let chocolateInjector = new ChocolateInjector(appFixture.componentInstance.injector); + let chocolateInjector = new ChocolateInjector(fixture.componentInstance.injector); // Set the selectedHost to be a ComponentPortal. - let testAppComponent = appFixture.debugElement.componentInstance; + let testAppComponent = fixture.debugElement.componentInstance; testAppComponent.selectedPortal = new ComponentPortal(PizzaMsg, null, chocolateInjector); - appFixture.detectChanges(); + fixture.detectChanges(); // Flush the attachment of the Portal. flushMicrotasks(); - appFixture.detectChanges(); + fixture.detectChanges(); // Expect that the content of the attached portal is present. - let hostContainer = appFixture.nativeElement.querySelector('.portal-container'); + let hostContainer = fixture.nativeElement.querySelector('.portal-container'); expect(hostContainer.textContent).toContain('Pizza'); expect(hostContainer.textContent).toContain('Chocolate'); })); it('should load a