refactor(core): Remove linker test references to TestComponentBuilder (#10869)

Removed TestComponentBuilder references from projection_integration_spec.ts
This commit is contained in:
Chuck Jazdzewski 2016-08-17 11:19:38 -07:00 committed by Kara
parent 40e160c22c
commit 4829fbb95c
1 changed files with 409 additions and 581 deletions

View File

@ -9,188 +9,126 @@
import {Component, Directive, ElementRef, TemplateRef, ViewContainerRef, ViewEncapsulation, forwardRef} from '@angular/core'; import {Component, Directive, ElementRef, TemplateRef, ViewContainerRef, ViewEncapsulation, forwardRef} from '@angular/core';
import {getAllDebugNodes} from '@angular/core/src/debug/debug_node'; import {getAllDebugNodes} from '@angular/core/src/debug/debug_node';
import {ViewMetadata} from '@angular/core/src/metadata/view'; import {ViewMetadata} from '@angular/core/src/metadata/view';
import {ComponentFixture} from '@angular/core/testing'; import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {AsyncTestCompleter, TestComponentBuilder, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal'; import {beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {expect} from '@angular/platform-browser/testing/matchers'; import {expect} from '@angular/platform-browser/testing/matchers';
export function main() { export function main() {
describe('projection', () => { describe('projection', () => {
it('should support simple components', beforeEach(() => TestBed.configureTestingModule({declarations: [MainComp, OtherComp, Simple]}));
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<simple>' +
'<div>A</div>' +
'</simple>',
directives: [Simple]
}))
.createAsync(MainComp)
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
async.done();
});
}));
it('should support simple components with text interpolation as direct children', it('should support simple components', () => {
inject( const template = '<simple><div>A</div></simple>';
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {set: {template}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { const main = TestBed.createComponent(MainComp);
tcb.overrideView(MainComp, new ViewMetadata({
template: '{{\'START(\'}}<simple>' + expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
});
it('should support simple components with text interpolation as direct children', () => {
const template = '{{\'START(\'}}<simple>' +
'{{text}}' + '{{text}}' +
'</simple>{{\')END\'}}', '</simple>{{\')END\'}}';
directives: [Simple] TestBed.overrideComponent(MainComp, {set: {template}});
})) const main = TestBed.createComponent(MainComp);
.createAsync(MainComp)
.then((main) => {
main.debugElement.componentInstance.text = 'A'; main.debugElement.componentInstance.text = 'A';
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('START(SIMPLE(A))END'); expect(main.debugElement.nativeElement).toHaveText('START(SIMPLE(A))END');
async.done();
}); });
}));
it('should support projecting text interpolation to a non bound element', it('should support projecting text interpolation to a non bound element', () => {
inject( TestBed.overrideComponent(
[TestComponentBuilder, AsyncTestCompleter], Simple, {set: {template: 'SIMPLE(<div><ng-content></ng-content></div>)'}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {set: {template: '<simple>{{text}}</simple>'}});
tcb.overrideView( const main = TestBed.createComponent(MainComp);
Simple,
new ViewMetadata(
{template: 'SIMPLE(<div><ng-content></ng-content></div>)', directives: []}))
.overrideView(
MainComp, new ViewMetadata(
{template: '<simple>{{text}}</simple>', directives: [Simple]}))
.createAsync(MainComp)
.then((main) => {
main.debugElement.componentInstance.text = 'A'; main.debugElement.componentInstance.text = 'A';
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)'); expect(main.debugElement.nativeElement).toHaveText('SIMPLE(A)');
async.done();
}); });
}));
it('should support projecting text interpolation to a non bound element with other bound elements after it', it('should support projecting text interpolation to a non bound element with other bound elements after it',
inject( () => {
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(Simple, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView( template: 'SIMPLE(<div><ng-content></ng-content></div><div [tabIndex]="0">EL</div>)'
Simple, new ViewMetadata({ }
template: });
'SIMPLE(<div><ng-content></ng-content></div><div [tabIndex]="0">EL</div>)', TestBed.overrideComponent(MainComp, {set: {template: '<simple>{{text}}</simple>'}});
directives: [] const main = TestBed.createComponent(MainComp);
}))
.overrideView(
MainComp, new ViewMetadata(
{template: '<simple>{{text}}</simple>', directives: [Simple]}))
.createAsync(MainComp)
.then((main) => {
main.debugElement.componentInstance.text = 'A'; main.debugElement.componentInstance.text = 'A';
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(AEL)'); expect(main.debugElement.nativeElement).toHaveText('SIMPLE(AEL)');
async.done();
}); });
}));
it('should project content components', it('should project content components', () => {
inject( TestBed.overrideComponent(
[TestComponentBuilder, AsyncTestCompleter], Simple, {set: {template: 'SIMPLE({{0}}|<ng-content></ng-content>|{{2}})'}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(OtherComp, {set: {template: '{{1}}'}});
tcb.overrideView(Simple, new ViewMetadata({ TestBed.overrideComponent(MainComp, {set: {template: '<simple><other></other></simple>'}});
template: 'SIMPLE({{0}}|<ng-content></ng-content>|{{2}})', const main = TestBed.createComponent(MainComp);
directives: []
}))
.overrideView(OtherComp, new ViewMetadata({template: '{{1}}', directives: []}))
.overrideView(MainComp, new ViewMetadata({
template: '<simple><other></other></simple>',
directives: [Simple, OtherComp]
}))
.createAsync(MainComp)
.then((main) => {
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('SIMPLE(0|1|2)'); expect(main.debugElement.nativeElement).toHaveText('SIMPLE(0|1|2)');
async.done();
}); });
}));
it('should not show the light dom even if there is no content tag', it('should not show the light dom even if there is no content tag', () => {
inject( TestBed.configureTestingModule({declarations: [Empty]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {set: {template: '<empty>A</empty>'}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { const main = TestBed.createComponent(MainComp);
tcb.overrideView(
MainComp, new ViewMetadata({template: '<empty>A</empty>', directives: [Empty]}))
.createAsync(MainComp)
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText(''); expect(main.debugElement.nativeElement).toHaveText('');
async.done();
}); });
}));
it('should support multiple content tags', it('should support multiple content tags', () => {
inject( TestBed.configureTestingModule({declarations: [MultipleContentTagsComponent]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<multiple-content-tags>' + template: '<multiple-content-tags>' +
'<div>B</div>' + '<div>B</div>' +
'<div>C</div>' + '<div>C</div>' +
'<div class="left">A</div>' + '<div class="left">A</div>' +
'</multiple-content-tags>', '</multiple-content-tags>'
directives: [MultipleContentTagsComponent] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText('(A, BC)'); expect(main.debugElement.nativeElement).toHaveText('(A, BC)');
async.done();
}); });
}));
it('should redistribute only direct children', it('should redistribute only direct children', () => {
inject( TestBed.configureTestingModule({declarations: [MultipleContentTagsComponent]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<multiple-content-tags>' + template: '<multiple-content-tags>' +
'<div>B<div class="left">A</div></div>' + '<div>B<div class="left">A</div></div>' +
'<div>C</div>' + '<div>C</div>' +
'</multiple-content-tags>', '</multiple-content-tags>'
directives: [MultipleContentTagsComponent] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText('(, BAC)'); expect(main.debugElement.nativeElement).toHaveText('(, BAC)');
async.done();
}); });
}));
it('should redistribute direct child viewcontainers when the light dom changes', it('should redistribute direct child viewcontainers when the light dom changes', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [MultipleContentTagsComponent, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView( set: {
MainComp, new ViewMetadata({
template: '<multiple-content-tags>' + template: '<multiple-content-tags>' +
'<template manual class="left"><div>A1</div></template>' + '<template manual class="left"><div>A1</div></template>' +
'<div>B</div>' + '<div>B</div>' +
'</multiple-content-tags>', '</multiple-content-tags>'
directives: [MultipleContentTagsComponent, ManualViewportDirective] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var viewportDirectives = var viewportDirectives = main.debugElement.children[0]
main.debugElement.children[0]
.childNodes.filter(By.directive(ManualViewportDirective)) .childNodes.filter(By.directive(ManualViewportDirective))
.map(de => de.injector.get(ManualViewportDirective)); .map(de => de.injector.get(ManualViewportDirective));
@ -201,76 +139,66 @@ export function main() {
viewportDirectives.forEach(d => d.hide()); viewportDirectives.forEach(d => d.hide());
expect(main.debugElement.nativeElement).toHaveText('(, B)'); expect(main.debugElement.nativeElement).toHaveText('(, B)');
async.done();
}); });
}));
it('should support nested components', it('should support nested components', () => {
inject( TestBed.configureTestingModule({declarations: [OuterWithIndirectNestedComponent]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<outer-with-indirect-nested>' + template: '<outer-with-indirect-nested>' +
'<div>A</div>' + '<div>A</div>' +
'<div>B</div>' + '<div>B</div>' +
'</outer-with-indirect-nested>', '</outer-with-indirect-nested>'
directives: [OuterWithIndirectNestedComponent] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText('OUTER(SIMPLE(AB))'); expect(main.debugElement.nativeElement).toHaveText('OUTER(SIMPLE(AB))');
async.done();
}); });
}));
it('should support nesting with content being direct child of a nested component', it('should support nesting with content being direct child of a nested component', () => {
inject( TestBed.configureTestingModule({
[TestComponentBuilder, AsyncTestCompleter], declarations:
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { [InnerComponent, InnerInnerComponent, OuterComponent, ManualViewportDirective]
tcb.overrideView(MainComp, new ViewMetadata({ });
TestBed.overrideComponent(MainComp, {
set: {
template: '<outer>' + template: '<outer>' +
'<template manual class="left"><div>A</div></template>' + '<template manual class="left"><div>A</div></template>' +
'<div>B</div>' + '<div>B</div>' +
'<div>C</div>' + '<div>C</div>' +
'</outer>', '</outer>'
directives: [OuterComponent, ManualViewportDirective], }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var viewportDirective = var viewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0] main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
expect(main.debugElement.nativeElement) expect(main.debugElement.nativeElement).toHaveText('OUTER(INNER(INNERINNER(,BC)))');
.toHaveText('OUTER(INNER(INNERINNER(,BC)))');
viewportDirective.show(); viewportDirective.show();
expect(main.debugElement.nativeElement) expect(main.debugElement.nativeElement).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
.toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
async.done();
}); });
}));
it('should redistribute when the shadow dom changes', it('should redistribute when the shadow dom changes', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [ConditionalContentComponent, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView(MainComp, new ViewMetadata({ set: {
template: '<conditional-content>' + template: '<conditional-content>' +
'<div class="left">A</div>' + '<div class="left">A</div>' +
'<div>B</div>' + '<div>B</div>' +
'<div>C</div>' + '<div>C</div>' +
'</conditional-content>', '</conditional-content>'
directives: [ConditionalContentComponent] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var viewportDirective = var viewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0] main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('(, BC)'); expect(main.debugElement.nativeElement).toHaveText('(, BC)');
@ -280,69 +208,48 @@ export function main() {
viewportDirective.hide(); viewportDirective.hide();
expect(main.debugElement.nativeElement).toHaveText('(, BC)'); expect(main.debugElement.nativeElement).toHaveText('(, BC)');
async.done();
}); });
}));
// GH-2095 - https://github.com/angular/angular/issues/2095 // GH-2095 - https://github.com/angular/angular/issues/2095
// important as we are removing the ng-content element during compilation, // important as we are removing the ng-content element during compilation,
// which could skrew up text node indices. // which could skrew up text node indices.
it('should support text nodes after content tags', it('should support text nodes after content tags', () => {
inject( TestBed.overrideComponent(MainComp, {set: {template: '<simple stringProp="text"></simple>'}});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { Simple, {set: {template: '<ng-content></ng-content><p>P,</p>{{stringProp}}'}});
const main = TestBed.createComponent(MainComp);
tcb.overrideView(
MainComp,
new ViewMetadata(
{template: '<simple stringProp="text"></simple>', directives: [Simple]}))
.overrideTemplate(Simple, '<ng-content></ng-content><p>P,</p>{{stringProp}}')
.createAsync(MainComp)
.then((main: ComponentFixture<any>) => {
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('P,text'); expect(main.debugElement.nativeElement).toHaveText('P,text');
async.done();
}); });
}));
// important as we are moving style tags around during compilation, // important as we are moving style tags around during compilation,
// which could skrew up text node indices. // which could skrew up text node indices.
it('should support text nodes after style tags', it('should support text nodes after style tags', () => {
inject( TestBed.overrideComponent(MainComp, {set: {template: '<simple stringProp="text"></simple>'}});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { Simple, {set: {template: '<style></style><p>P,</p>{{stringProp}}'}});
const main = TestBed.createComponent(MainComp);
tcb.overrideView(
MainComp,
new ViewMetadata(
{template: '<simple stringProp="text"></simple>', directives: [Simple]}))
.overrideTemplate(Simple, '<style></style><p>P,</p>{{stringProp}}')
.createAsync(MainComp)
.then((main: ComponentFixture<any>) => {
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('P,text'); expect(main.debugElement.nativeElement).toHaveText('P,text');
async.done();
}); });
}));
it('should support moving non projected light dom around', it('should support moving non projected light dom around', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [Empty, ProjectDirective, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView(MainComp, new ViewMetadata({ set: {
template: '<empty>' + template: '<empty>' +
' <template manual><div>A</div></template>' + ' <template manual><div>A</div></template>' +
'</empty>' + '</empty>' +
'START(<div project></div>)END', 'START(<div project></div>)END'
directives: [Empty, ProjectDirective, ManualViewportDirective], }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var sourceDirective: any /** TODO #9100 */; var sourceDirective: any;
// We can't use the child nodes to get a hold of this because it's not in the dom // We can't use the child nodes to get a hold of this because it's not in the dom
// at // at
@ -354,68 +261,58 @@ export function main() {
}); });
var projectDirective: ProjectDirective = var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0] main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].injector.get(
.injector.get(ProjectDirective); ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('START()END'); expect(main.debugElement.nativeElement).toHaveText('START()END');
projectDirective.show(sourceDirective.templateRef); projectDirective.show(sourceDirective.templateRef);
expect(main.debugElement.nativeElement).toHaveText('START(A)END'); expect(main.debugElement.nativeElement).toHaveText('START(A)END');
async.done();
}); });
}));
it('should support moving projected light dom around', it('should support moving projected light dom around', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [Empty, ProjectDirective, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView( set: {
MainComp, new ViewMetadata({
template: '<simple><template manual><div>A</div></template></simple>' + template: '<simple><template manual><div>A</div></template></simple>' +
'START(<div project></div>)END', 'START(<div project></div>)END'
directives: [Simple, ProjectDirective, ManualViewportDirective], }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var sourceDirective: ManualViewportDirective = var sourceDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0] main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
var projectDirective: ProjectDirective = var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0] main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].injector.get(
.injector.get(ProjectDirective); ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('SIMPLE()START()END'); expect(main.debugElement.nativeElement).toHaveText('SIMPLE()START()END');
projectDirective.show(sourceDirective.templateRef); projectDirective.show(sourceDirective.templateRef);
expect(main.debugElement.nativeElement).toHaveText('SIMPLE()START(A)END'); expect(main.debugElement.nativeElement).toHaveText('SIMPLE()START(A)END');
async.done();
}); });
}));
it('should support moving ng-content around', it('should support moving ng-content around', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [ConditionalContentComponent, ProjectDirective, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView( set: {
MainComp, new ViewMetadata({
template: '<conditional-content>' + template: '<conditional-content>' +
'<div class="left">A</div>' + '<div class="left">A</div>' +
'<div>B</div>' + '<div>B</div>' +
'</conditional-content>' + '</conditional-content>' +
'START(<div project></div>)END', 'START(<div project></div>)END'
directives: [ }
ConditionalContentComponent, ProjectDirective, ManualViewportDirective });
] const main = TestBed.createComponent(MainComp);
}))
.createAsync(MainComp)
.then((main) => {
var sourceDirective: ManualViewportDirective = var sourceDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0] main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
var projectDirective: ProjectDirective = var projectDirective: ProjectDirective =
main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0] main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].injector.get(
.injector.get(ProjectDirective); ProjectDirective);
expect(main.debugElement.nativeElement).toHaveText('(, B)START()END'); expect(main.debugElement.nativeElement).toHaveText('(, B)START()END');
projectDirective.show(sourceDirective.templateRef); projectDirective.show(sourceDirective.templateRef);
@ -425,51 +322,35 @@ export function main() {
// times... // times...
projectDirective.show(sourceDirective.templateRef); projectDirective.show(sourceDirective.templateRef);
expect(main.debugElement.nativeElement).toHaveText('(, B)START(A)END'); expect(main.debugElement.nativeElement).toHaveText('(, B)START(A)END');
async.done();
}); });
}));
// Note: This does not use a ng-content element, but // Note: This does not use a ng-content element, but
// is still important as we are merging proto views independent of // is still important as we are merging proto views independent of
// the presence of ng-content elements! // the presence of ng-content elements!
it('should still allow to implement a recursive trees', it('should still allow to implement a recursive trees', () => {
inject( TestBed.configureTestingModule({declarations: [Tree, ManualViewportDirective]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {set: {template: '<tree></tree>'}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { const main = TestBed.createComponent(MainComp);
tcb.overrideView(
MainComp, new ViewMetadata({template: '<tree></tree>', directives: [Tree]}))
.createAsync(MainComp)
.then((main) => {
main.detectChanges(); main.detectChanges();
var manualDirective: ManualViewportDirective = var manualDirective: ManualViewportDirective =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0] main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('TREE(0:)'); expect(main.debugElement.nativeElement).toHaveText('TREE(0:)');
manualDirective.show(); manualDirective.show();
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE(1:))'); expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE(1:))');
async.done();
}); });
}));
// Note: This does not use a ng-content element, but // Note: This does not use a ng-content element, but
// is still important as we are merging proto views independent of // is still important as we are merging proto views independent of
// the presence of ng-content elements! // the presence of ng-content elements!
it('should still allow to implement a recursive trees via multiple components', it('should still allow to implement a recursive trees via multiple components', () => {
inject( TestBed.configureTestingModule({declarations: [Tree, Tree2, ManualViewportDirective]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {set: {template: '<tree></tree>'}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(
tcb.overrideView( Tree, {set: {template: 'TREE({{depth}}:<tree2 *manual [depth]="depth+1"></tree2>)'}});
MainComp, new ViewMetadata({template: '<tree></tree>', directives: [Tree]})) const main = TestBed.createComponent(MainComp);
.overrideView(
Tree, new ViewMetadata({
template: 'TREE({{depth}}:<tree2 *manual [depth]="depth+1"></tree2>)',
directives: [Tree2, ManualViewportDirective]
}))
.createAsync(MainComp)
.then((main) => {
main.detectChanges(); main.detectChanges();
@ -483,51 +364,43 @@ export function main() {
expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE2(1:))'); expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE2(1:))');
var tree2 = main.debugElement.query(By.directive(Tree2)); var tree2 = main.debugElement.query(By.directive(Tree2));
manualDirective = manualDirective = tree2.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
tree2.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
ManualViewportDirective); ManualViewportDirective);
manualDirective.show(); manualDirective.show();
main.detectChanges(); main.detectChanges();
expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE2(1:TREE(2:)))'); expect(main.debugElement.nativeElement).toHaveText('TREE(0:TREE2(1:TREE(2:)))');
async.done();
}); });
}));
if (getDOM().supportsNativeShadowDOM()) { if (getDOM().supportsNativeShadowDOM()) {
it('should support native content projection and isolate styles per component', it('should support native content projection and isolate styles per component', () => {
inject( TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<simple-native1><div>A</div></simple-native1>' + template: '<simple-native1><div>A</div></simple-native1>' +
'<simple-native2><div>B</div></simple-native2>', '<simple-native2><div>B</div></simple-native2>'
directives: [SimpleNative1, SimpleNative2] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var childNodes = getDOM().childNodes(main.debugElement.nativeElement); var childNodes = getDOM().childNodes(main.debugElement.nativeElement);
expect(childNodes[0]).toHaveText('div {color: red}SIMPLE1(A)'); expect(childNodes[0]).toHaveText('div {color: red}SIMPLE1(A)');
expect(childNodes[1]).toHaveText('div {color: blue}SIMPLE2(B)'); expect(childNodes[1]).toHaveText('div {color: blue}SIMPLE2(B)');
main.destroy(); main.destroy();
async.done();
}); });
}));
} }
if (getDOM().supportsDOMEvents()) { if (getDOM().supportsDOMEvents()) {
it('should support non emulated styles', it('should support non emulated styles', () => {
inject( TestBed.configureTestingModule({declarations: [OtherComp]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<div class="redStyle"></div>', template: '<div class="redStyle"></div>',
styles: ['.redStyle { color: red}'], styles: ['.redStyle { color: red}'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
directives: [OtherComp] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var mainEl = main.debugElement.nativeElement; var mainEl = main.debugElement.nativeElement;
var div1 = getDOM().firstChild(mainEl); var div1 = getDOM().firstChild(mainEl);
var div2 = getDOM().createElement('div'); var div2 = getDOM().createElement('div');
@ -535,42 +408,35 @@ export function main() {
getDOM().appendChild(mainEl, div2); getDOM().appendChild(mainEl, div2);
expect(getDOM().getComputedStyle(div1).color).toEqual('rgb(255, 0, 0)'); expect(getDOM().getComputedStyle(div1).color).toEqual('rgb(255, 0, 0)');
expect(getDOM().getComputedStyle(div2).color).toEqual('rgb(255, 0, 0)'); expect(getDOM().getComputedStyle(div2).color).toEqual('rgb(255, 0, 0)');
async.done();
}); });
}));
it('should support emulated style encapsulation', it('should support emulated style encapsulation', () => {
inject( TestBed.configureTestingModule({declarations: [OtherComp]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { set: {
tcb.overrideView(MainComp, new ViewMetadata({
template: '<div></div>', template: '<div></div>',
styles: ['div { color: red}'], styles: ['div { color: red}'],
encapsulation: ViewEncapsulation.Emulated encapsulation: ViewEncapsulation.Emulated,
})) }
.createAsync(MainComp) });
.then((main) => { const main = TestBed.createComponent(MainComp);
var mainEl = main.debugElement.nativeElement; var mainEl = main.debugElement.nativeElement;
var div1 = getDOM().firstChild(mainEl); var div1 = getDOM().firstChild(mainEl);
var div2 = getDOM().createElement('div'); var div2 = getDOM().createElement('div');
getDOM().appendChild(mainEl, div2); getDOM().appendChild(mainEl, div2);
expect(getDOM().getComputedStyle(div1).color).toEqual('rgb(255, 0, 0)'); expect(getDOM().getComputedStyle(div1).color).toEqual('rgb(255, 0, 0)');
expect(getDOM().getComputedStyle(div2).color).toEqual('rgb(0, 0, 0)'); expect(getDOM().getComputedStyle(div2).color).toEqual('rgb(0, 0, 0)');
async.done();
}); });
}));
} }
it('should support nested conditionals that contain ng-contents', it('should support nested conditionals that contain ng-contents', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [ConditionalTextComponent, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(
tcb.overrideView(MainComp, new ViewMetadata({ MainComp, {set: {template: `<conditional-text>a</conditional-text>`}});
template: `<conditional-text>a</conditional-text>`, const main = TestBed.createComponent(MainComp);
directives: [ConditionalTextComponent]
}))
.createAsync(MainComp)
.then((main) => {
expect(main.debugElement.nativeElement).toHaveText('MAIN()'); expect(main.debugElement.nativeElement).toHaveText('MAIN()');
var viewportElement = var viewportElement =
@ -578,75 +444,56 @@ export function main() {
viewportElement.injector.get(ManualViewportDirective).show(); viewportElement.injector.get(ManualViewportDirective).show();
expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST())'); expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST())');
viewportElement = viewportElement = main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[1];
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[1];
viewportElement.injector.get(ManualViewportDirective).show(); viewportElement.injector.get(ManualViewportDirective).show();
expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST(SECOND(a)))'); expect(main.debugElement.nativeElement).toHaveText('MAIN(FIRST(SECOND(a)))');
async.done();
}); });
}));
it('should allow to switch the order of nested components via ng-content', it('should allow to switch the order of nested components via ng-content', () => {
inject( TestBed.configureTestingModule({declarations: [CmpA, CmpB]});
[TestComponentBuilder, AsyncTestCompleter], TestBed.overrideComponent(MainComp, {set: {template: `<cmp-a><cmp-b></cmp-b></cmp-a>`}});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { const main = TestBed.createComponent(MainComp);
tcb.overrideView(MainComp, new ViewMetadata({
template: `<cmp-a><cmp-b></cmp-b></cmp-a>`,
directives: [CmpA, CmpB],
}))
.createAsync(MainComp)
.then((main) => {
main.detectChanges(); main.detectChanges();
expect(getDOM().getInnerHTML(main.debugElement.nativeElement)) expect(getDOM().getInnerHTML(main.debugElement.nativeElement))
.toEqual( .toEqual(
'<cmp-a><cmp-b><cmp-d><d>cmp-d</d></cmp-d></cmp-b>' + '<cmp-a><cmp-b><cmp-d><d>cmp-d</d></cmp-d></cmp-b>' +
'<cmp-c><c>cmp-c</c></cmp-c></cmp-a>'); '<cmp-c><c>cmp-c</c></cmp-c></cmp-a>');
async.done();
}); });
}));
it('should create nested components in the right order', it('should create nested components in the right order', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [CmpA1, CmpA2, CmpB11, CmpB12, CmpB21, CmpB22]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {set: {template: `<cmp-a1></cmp-a1><cmp-a2></cmp-a2>`}});
tcb.overrideView(MainComp, new ViewMetadata({ const main = TestBed.createComponent(MainComp);
template: `<cmp-a1></cmp-a1><cmp-a2></cmp-a2>`,
directives: [CmpA1, CmpA2],
}))
.createAsync(MainComp)
.then((main) => {
main.detectChanges(); main.detectChanges();
expect(getDOM().getInnerHTML(main.debugElement.nativeElement)) expect(getDOM().getInnerHTML(main.debugElement.nativeElement))
.toEqual( .toEqual(
'<cmp-a1>a1<cmp-b11>b11</cmp-b11><cmp-b12>b12</cmp-b12></cmp-a1>' + '<cmp-a1>a1<cmp-b11>b11</cmp-b11><cmp-b12>b12</cmp-b12></cmp-a1>' +
'<cmp-a2>a2<cmp-b21>b21</cmp-b21><cmp-b22>b22</cmp-b22></cmp-a2>'); '<cmp-a2>a2<cmp-b21>b21</cmp-b21><cmp-b22>b22</cmp-b22></cmp-a2>');
async.done();
}); });
}));
it('should project filled view containers into a view container', it('should project filled view containers into a view container', () => {
inject( TestBed.configureTestingModule(
[TestComponentBuilder, AsyncTestCompleter], {declarations: [ConditionalContentComponent, ManualViewportDirective]});
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => { TestBed.overrideComponent(MainComp, {
tcb.overrideView( set: {
MainComp, new ViewMetadata({
template: '<conditional-content>' + template: '<conditional-content>' +
'<div class="left">A</div>' + '<div class="left">A</div>' +
'<template manual class="left">B</template>' + '<template manual class="left">B</template>' +
'<div class="left">C</div>' + '<div class="left">C</div>' +
'<div>D</div>' + '<div>D</div>' +
'</conditional-content>', '</conditional-content>'
directives: [ConditionalContentComponent, ManualViewportDirective] }
})) });
.createAsync(MainComp) const main = TestBed.createComponent(MainComp);
.then((main) => {
var conditionalComp = var conditionalComp = main.debugElement.query(By.directive(ConditionalContentComponent));
main.debugElement.query(By.directive(ConditionalContentComponent));
var viewViewportDir = var viewViewportDir =
conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[0] conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[0].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
expect(main.debugElement.nativeElement).toHaveText('(, D)'); expect(main.debugElement.nativeElement).toHaveText('(, D)');
expect(main.debugElement.nativeElement).toHaveText('(, D)'); expect(main.debugElement.nativeElement).toHaveText('(, D)');
@ -656,8 +503,8 @@ export function main() {
expect(main.debugElement.nativeElement).toHaveText('(AC, D)'); expect(main.debugElement.nativeElement).toHaveText('(AC, D)');
var contentViewportDir = var contentViewportDir =
conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[1] conditionalComp.queryAllNodes(By.directive(ManualViewportDirective))[1].injector.get(
.injector.get(ManualViewportDirective); ManualViewportDirective);
contentViewportDir.show(); contentViewportDir.show();
@ -667,20 +514,16 @@ export function main() {
// the content viewport's views // the content viewport's views
viewViewportDir.hide(); viewViewportDir.hide();
expect(main.debugElement.nativeElement).toHaveText('(, D)'); expect(main.debugElement.nativeElement).toHaveText('(, D)');
async.done();
}); });
}));
}); });
} }
@Component({selector: 'main', template: '', directives: []}) @Component({selector: 'main', template: ''})
class MainComp { class MainComp {
text: string = ''; text: string = '';
} }
@Component({selector: 'other', template: '', directives: []}) @Component({selector: 'other', template: ''})
class OtherComp { class OtherComp {
text: string = ''; text: string = '';
} }
@ -689,7 +532,6 @@ class OtherComp {
selector: 'simple', selector: 'simple',
inputs: ['stringProp'], inputs: ['stringProp'],
template: 'SIMPLE(<ng-content></ng-content>)', template: 'SIMPLE(<ng-content></ng-content>)',
directives: []
}) })
class Simple { class Simple {
stringProp: string = ''; stringProp: string = '';
@ -698,7 +540,6 @@ class Simple {
@Component({ @Component({
selector: 'simple-native1', selector: 'simple-native1',
template: 'SIMPLE1(<content></content>)', template: 'SIMPLE1(<content></content>)',
directives: [],
encapsulation: ViewEncapsulation.Native, encapsulation: ViewEncapsulation.Native,
styles: ['div {color: red}'] styles: ['div {color: red}']
}) })
@ -708,7 +549,6 @@ class SimpleNative1 {
@Component({ @Component({
selector: 'simple-native2', selector: 'simple-native2',
template: 'SIMPLE2(<content></content>)', template: 'SIMPLE2(<content></content>)',
directives: [],
encapsulation: ViewEncapsulation.Native, encapsulation: ViewEncapsulation.Native,
styles: ['div {color: blue}'] styles: ['div {color: blue}']
}) })
@ -722,7 +562,6 @@ class Empty {
@Component({ @Component({
selector: 'multiple-content-tags', selector: 'multiple-content-tags',
template: '(<ng-content SELECT=".left"></ng-content>, <ng-content></ng-content>)', template: '(<ng-content SELECT=".left"></ng-content>, <ng-content></ng-content>)',
directives: []
}) })
class MultipleContentTagsComponent { class MultipleContentTagsComponent {
} }
@ -744,7 +583,6 @@ class ProjectDirective {
@Component({ @Component({
selector: 'outer-with-indirect-nested', selector: 'outer-with-indirect-nested',
template: 'OUTER(<simple><div><ng-content></ng-content></div></simple>)', template: 'OUTER(<simple><div><ng-content></ng-content></div></simple>)',
directives: [Simple]
}) })
class OuterWithIndirectNestedComponent { class OuterWithIndirectNestedComponent {
} }
@ -753,7 +591,6 @@ class OuterWithIndirectNestedComponent {
selector: 'outer', selector: 'outer',
template: template:
'OUTER(<inner><ng-content select=".left" class="left"></ng-content><ng-content></ng-content></inner>)', 'OUTER(<inner><ng-content select=".left" class="left"></ng-content><ng-content></ng-content></inner>)',
directives: [forwardRef(() => InnerComponent)]
}) })
class OuterComponent { class OuterComponent {
} }
@ -762,7 +599,6 @@ class OuterComponent {
selector: 'inner', selector: 'inner',
template: template:
'INNER(<innerinner><ng-content select=".left" class="left"></ng-content><ng-content></ng-content></innerinner>)', 'INNER(<innerinner><ng-content select=".left" class="left"></ng-content><ng-content></ng-content></innerinner>)',
directives: [forwardRef(() => InnerInnerComponent)]
}) })
class InnerComponent { class InnerComponent {
} }
@ -770,7 +606,6 @@ class InnerComponent {
@Component({ @Component({
selector: 'innerinner', selector: 'innerinner',
template: 'INNERINNER(<ng-content select=".left"></ng-content>,<ng-content></ng-content>)', template: 'INNERINNER(<ng-content select=".left"></ng-content>,<ng-content></ng-content>)',
directives: []
}) })
class InnerInnerComponent { class InnerInnerComponent {
} }
@ -779,7 +614,6 @@ class InnerInnerComponent {
selector: 'conditional-content', selector: 'conditional-content',
template: template:
'<div>(<div *manual><ng-content select=".left"></ng-content></div>, <ng-content></ng-content>)</div>', '<div>(<div *manual><ng-content select=".left"></ng-content></div>, <ng-content></ng-content>)</div>',
directives: [ManualViewportDirective]
}) })
class ConditionalContentComponent { class ConditionalContentComponent {
} }
@ -788,7 +622,6 @@ class ConditionalContentComponent {
selector: 'conditional-text', selector: 'conditional-text',
template: template:
'MAIN(<template manual>FIRST(<template manual>SECOND(<ng-content></ng-content>)</template>)</template>)', 'MAIN(<template manual>FIRST(<template manual>SECOND(<ng-content></ng-content>)</template>)</template>)',
directives: [ManualViewportDirective]
}) })
class ConditionalTextComponent { class ConditionalTextComponent {
} }
@ -796,7 +629,6 @@ class ConditionalTextComponent {
@Component({ @Component({
selector: 'tab', selector: 'tab',
template: '<div><div *manual>TAB(<ng-content></ng-content>)</div></div>', template: '<div><div *manual>TAB(<ng-content></ng-content>)</div></div>',
directives: [ManualViewportDirective]
}) })
class Tab { class Tab {
} }
@ -805,7 +637,6 @@ class Tab {
selector: 'tree2', selector: 'tree2',
inputs: ['depth'], inputs: ['depth'],
template: 'TREE2({{depth}}:<tree *manual [depth]="depth+1"></tree>)', template: 'TREE2({{depth}}:<tree *manual [depth]="depth+1"></tree>)',
directives: [ManualViewportDirective, forwardRef(() => Tree)]
}) })
class Tree2 { class Tree2 {
depth = 0; depth = 0;
@ -815,7 +646,6 @@ class Tree2 {
selector: 'tree', selector: 'tree',
inputs: ['depth'], inputs: ['depth'],
template: 'TREE({{depth}}:<tree *manual [depth]="depth+1"></tree>)', template: 'TREE({{depth}}:<tree *manual [depth]="depth+1"></tree>)',
directives: [ManualViewportDirective, Tree, forwardRef(() => Tree)]
}) })
class Tree { class Tree {
depth = 0; depth = 0;
@ -870,7 +700,6 @@ class CmpB22 {
@Component({ @Component({
selector: 'cmp-a1', selector: 'cmp-a1',
template: `{{'a1'}}<cmp-b11></cmp-b11><cmp-b12></cmp-b12>`, template: `{{'a1'}}<cmp-b11></cmp-b11><cmp-b12></cmp-b12>`,
directives: [CmpB11, CmpB12]
}) })
class CmpA1 { class CmpA1 {
} }
@ -878,7 +707,6 @@ class CmpA1 {
@Component({ @Component({
selector: 'cmp-a2', selector: 'cmp-a2',
template: `{{'a2'}}<cmp-b21></cmp-b21><cmp-b22></cmp-b22>`, template: `{{'a2'}}<cmp-b21></cmp-b21><cmp-b22></cmp-b22>`,
directives: [CmpB21, CmpB22]
}) })
class CmpA2 { class CmpA2 {
} }