refactor(core): Removed linker test references to TestComponentBuilder (#10903)
Removed references to TestComponentBuilder from: query_integration_spec.ts regression_integration_spec.ts security_integration_spec.ts view_injector_integration_spec.ts
This commit is contained in:
parent
c48021ab97
commit
a5c0349d88
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@ import {NgClass, NgIf} from '@angular/common';
|
||||
import {Component, Injector, OpaqueToken, Pipe, PipeTransform, forwardRef} from '@angular/core';
|
||||
import {ViewMetadata} from '@angular/core/src/metadata/view';
|
||||
import {TestBed} 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 {expect} from '@angular/platform-browser/testing/matchers';
|
||||
|
||||
export function main() {
|
||||
@ -23,199 +23,134 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
// Place to put reproductions for regressions
|
||||
describe('regressions', () => {
|
||||
|
||||
describe('platform pipes', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureCompiler({useJit: useJit});
|
||||
TestBed.configureTestingModule({declarations: [PlatformPipe]});
|
||||
});
|
||||
beforeEach(() => { TestBed.configureTestingModule({declarations: [MyComp1, PlatformPipe]}); });
|
||||
|
||||
describe('platform pipes', () => {
|
||||
beforeEach(() => { TestBed.configureCompiler({useJit: useJit}); });
|
||||
|
||||
it('should overwrite them by custom pipes', () => {
|
||||
TestBed.configureTestingModule({declarations: [CustomPipe]});
|
||||
const template = '{{true | somePipe}}';
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
it('should overwrite them by custom pipes',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideView(
|
||||
MyComp1,
|
||||
new ViewMetadata({template: '{{true | somePipe}}', pipes: [CustomPipe]}))
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('someCustomPipe');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('expressions', () => {
|
||||
it('should evaluate conditional and boolean operators with right precedence - #8244', () => {
|
||||
const template = `{{'red' + (true ? ' border' : '')}}`;
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
it('should evaluate conditional and boolean operators with right precedence - #8244',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideView(
|
||||
MyComp1, new ViewMetadata({template: `{{'red' + (true ? ' border' : '')}}`}))
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('red border');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should evaluate conditional and unary operators with right precedence - #8235',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideView(MyComp1, new ViewMetadata({template: `{{!null?.length}}`}))
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => {
|
||||
it('should evaluate conditional and unary operators with right precedence - #8235', () => {
|
||||
const template = `{{!null?.length}}`;
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('true');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should only evaluate stateful pipes once - #10639',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideView(
|
||||
MyComp1,
|
||||
new ViewMetadata(
|
||||
{template: '{{(null|countingPipe)?.value}}', pipes: [CountingPipe]}))
|
||||
.createAsync(MyComp1)
|
||||
.then(fixture => {
|
||||
it('should only evaluate stateful pipes once - #10639', () => {
|
||||
TestBed.configureTestingModule({declarations: [CountingPipe]});
|
||||
const template = '{{(null|countingPipe)?.value}}';
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
CountingPipe.reset();
|
||||
fixture.detectChanges(/* checkNoChanges */ false);
|
||||
expect(fixture.nativeElement).toHaveText('counting pipe value');
|
||||
expect(CountingPipe.calls).toBe(1);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should only evaluate methods once - #10639',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideView(MyCountingComp, new ViewMetadata({template: '{{method()?.value}}'}))
|
||||
.createAsync(MyCountingComp)
|
||||
.then(fixture => {
|
||||
it('should only evaluate methods once - #10639', () => {
|
||||
TestBed.configureTestingModule({declarations: [MyCountingComp]});
|
||||
const template = '{{method()?.value}}';
|
||||
TestBed.overrideComponent(MyCountingComp, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyCountingComp);
|
||||
|
||||
MyCountingComp.reset();
|
||||
fixture.detectChanges(/* checkNoChanges */ false);
|
||||
expect(fixture.nativeElement).toHaveText('counting method value');
|
||||
expect(MyCountingComp.calls).toBe(1);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('providers', () => {
|
||||
function createInjector(tcb: TestComponentBuilder, proviers: any[]): Promise<Injector> {
|
||||
return tcb.overrideProviders(MyComp1, [proviers])
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => fixture.componentInstance.injector);
|
||||
function createInjector(providers: any[]): Injector {
|
||||
TestBed.overrideComponent(MyComp1, {add: {providers}});
|
||||
return TestBed.createComponent(MyComp1).componentInstance.injector;
|
||||
}
|
||||
|
||||
it('should support providers with an OpaqueToken that contains a `.` in the name',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
it('should support providers with an OpaqueToken that contains a `.` in the name', () => {
|
||||
var token = new OpaqueToken('a.b');
|
||||
var tokenValue = 1;
|
||||
createInjector(tcb, [
|
||||
{provide: token, useValue: tokenValue}
|
||||
]).then((injector: Injector) => {
|
||||
const injector = createInjector([{provide: token, useValue: tokenValue}]);
|
||||
expect(injector.get(token)).toEqual(tokenValue);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should support providers with string token with a `.` in it',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
it('should support providers with string token with a `.` in it', () => {
|
||||
var token = 'a.b';
|
||||
var tokenValue = 1;
|
||||
createInjector(tcb, [
|
||||
{provide: token, useValue: tokenValue}
|
||||
]).then((injector: Injector) => {
|
||||
expect(injector.get(token)).toEqual(tokenValue);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
const injector = createInjector([{provide: token, useValue: tokenValue}]);
|
||||
|
||||
it('should support providers with an anonymous function',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
expect(injector.get(token)).toEqual(tokenValue);
|
||||
});
|
||||
|
||||
it('should support providers with an anonymous function', () => {
|
||||
var token = () => true;
|
||||
var tokenValue = 1;
|
||||
createInjector(tcb, [
|
||||
{provide: token, useValue: tokenValue}
|
||||
]).then((injector: Injector) => {
|
||||
expect(injector.get(token)).toEqual(tokenValue);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
const injector = createInjector([{provide: token, useValue: tokenValue}]);
|
||||
|
||||
it('should support providers with an OpaqueToken that has a StringMap as value',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
expect(injector.get(token)).toEqual(tokenValue);
|
||||
});
|
||||
|
||||
it('should support providers with an OpaqueToken that has a StringMap as value', () => {
|
||||
var token1 = new OpaqueToken('someToken');
|
||||
var token2 = new OpaqueToken('someToken');
|
||||
var tokenValue1 = {'a': 1};
|
||||
var tokenValue2 = {'a': 1};
|
||||
createInjector(tcb, [
|
||||
{provide: token1, useValue: tokenValue1},
|
||||
{provide: token2, useValue: tokenValue2}
|
||||
]).then((injector: Injector) => {
|
||||
const injector = createInjector(
|
||||
[{provide: token1, useValue: tokenValue1}, {provide: token2, useValue: tokenValue2}]);
|
||||
|
||||
expect(injector.get(token1)).toEqual(tokenValue1);
|
||||
expect(injector.get(token2)).toEqual(tokenValue2);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should allow logging a previous elements class binding via interpolation',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
tcb.overrideTemplate(
|
||||
MyComp1, `<div [class.a]="true" #el>Class: {{el.className}}</div>`)
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => {
|
||||
it('should allow logging a previous elements class binding via interpolation', () => {
|
||||
const template = `<div [class.a]="true" #el>Class: {{el.className}}</div>`;
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('Class: a');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should support ngClass before a component and content projection inside of an ngIf',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
|
||||
tcb.overrideView(
|
||||
MyComp1, new ViewMetadata({
|
||||
template: `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`,
|
||||
directives: [NgClass, NgIf, CmpWithNgContent]
|
||||
}))
|
||||
.createAsync(MyComp1)
|
||||
.then((fixture) => {
|
||||
it('should support ngClass before a component and content projection inside of an ngIf', () => {
|
||||
TestBed.configureTestingModule({declarations: [CmpWithNgContent]});
|
||||
const template = `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`;
|
||||
TestBed.overrideComponent(MyComp1, {set: {template}});
|
||||
const fixture = TestBed.createComponent(MyComp1);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('ABC');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should handle mutual recursion entered from multiple sides - #7084',
|
||||
inject(
|
||||
[TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
|
||||
tcb.createAsync(FakeRecursiveComp).then((fixture) => {
|
||||
it('should handle mutual recursion entered from multiple sides - #7084', () => {
|
||||
TestBed.configureTestingModule({declarations: [FakeRecursiveComp, LeftComp, RightComp]});
|
||||
const fixture = TestBed.createComponent(FakeRecursiveComp);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('[]');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -262,10 +197,6 @@ class CountingPipe implements PipeTransform {
|
||||
@Component({
|
||||
selector: 'left',
|
||||
template: `L<right *ngIf="false"></right>`,
|
||||
directives: [
|
||||
NgIf,
|
||||
forwardRef(() => RightComp),
|
||||
]
|
||||
})
|
||||
class LeftComp {
|
||||
}
|
||||
@ -273,10 +204,6 @@ class LeftComp {
|
||||
@Component({
|
||||
selector: 'right',
|
||||
template: `R<left *ngIf="false"></left>`,
|
||||
directives: [
|
||||
NgIf,
|
||||
forwardRef(() => LeftComp),
|
||||
]
|
||||
})
|
||||
class RightComp {
|
||||
}
|
||||
@ -284,11 +211,6 @@ class RightComp {
|
||||
@Component({
|
||||
selector: 'fakeRecursiveComp',
|
||||
template: `[<left *ngIf="false"></left><right *ngIf="false"></right>]`,
|
||||
directives: [
|
||||
NgIf,
|
||||
forwardRef(() => LeftComp),
|
||||
forwardRef(() => RightComp),
|
||||
]
|
||||
})
|
||||
export class FakeRecursiveComp {
|
||||
}
|
||||
|
@ -7,42 +7,30 @@
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core/src/metadata';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {AsyncTestCompleter, TestComponentBuilder, afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
|
||||
import {TestBed, getTestBed} from '@angular/core/testing';
|
||||
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {DomSanitizationService} from '@angular/platform-browser/src/security/dom_sanitization_service';
|
||||
|
||||
|
||||
export function main() {
|
||||
describe('jit', () => { declareTests({useJit: true}); });
|
||||
|
||||
describe('no jit', () => { declareTests({useJit: false}); });
|
||||
}
|
||||
|
||||
@Component({selector: 'my-comp', template: '', directives: []})
|
||||
@Component({selector: 'my-comp', template: ''})
|
||||
class SecuredComponent {
|
||||
ctxProp: string;
|
||||
constructor() { this.ctxProp = 'some value'; }
|
||||
}
|
||||
|
||||
function itAsync(msg: string, injections: Function[], f: Function): void;
|
||||
function itAsync(
|
||||
msg: string, f: (tcb: TestComponentBuilder, atc: AsyncTestCompleter) => void): void;
|
||||
function itAsync(
|
||||
msg: string, f: Function[] | ((tcb: TestComponentBuilder, atc: AsyncTestCompleter) => void),
|
||||
fn?: Function): void {
|
||||
if (f instanceof Function) {
|
||||
it(msg, inject([TestComponentBuilder, AsyncTestCompleter], <Function>f));
|
||||
} else {
|
||||
let injections = f;
|
||||
it(msg, inject(injections, fn));
|
||||
}
|
||||
}
|
||||
|
||||
function declareTests({useJit}: {useJit: boolean}) {
|
||||
describe('security integration tests', function() {
|
||||
|
||||
beforeEach(() => { TestBed.configureCompiler({useJit: useJit}); });
|
||||
beforeEach(() => {
|
||||
TestBed.configureCompiler({useJit: useJit});
|
||||
TestBed.configureTestingModule({declarations: [SecuredComponent]});
|
||||
});
|
||||
|
||||
let originalLog: (msg: any) => any;
|
||||
beforeEach(() => {
|
||||
@ -52,91 +40,68 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
afterEach(() => { getDOM().log = originalLog; });
|
||||
|
||||
|
||||
itAsync(
|
||||
'should disallow binding on*', (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
let tpl = `<div [attr.onclick]="ctxProp"></div>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then(v => async.done(new Error('unexpected success')))
|
||||
.catch((e) => {
|
||||
it('should disallow binding on*', () => {
|
||||
const template = `<div [attr.onclick]="ctxProp"></div>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
try {
|
||||
TestBed.createComponent(SecuredComponent);
|
||||
throw 'Should throw';
|
||||
} catch (e) {
|
||||
expect(e.message).toContain(
|
||||
`Template parse errors:\n` +
|
||||
`Binding to event attribute 'onclick' is disallowed ` +
|
||||
`for security reasons, please use (click)=... `);
|
||||
async.done();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('safe HTML values', function() {
|
||||
itAsync(
|
||||
'should not escape values marked as trusted',
|
||||
[TestComponentBuilder, AsyncTestCompleter, DomSanitizationService],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter,
|
||||
sanitizer: DomSanitizationService) => {
|
||||
let tpl = `<a [href]="ctxProp">Link Title</a>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should not escape values marked as trusted', () => {
|
||||
const template = `<a [href]="ctxProp">Link Title</a>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
const sanitizer: DomSanitizationService = getTestBed().get(DomSanitizationService);
|
||||
|
||||
let e = fixture.debugElement.children[0].nativeElement;
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
let trusted = sanitizer.bypassSecurityTrustUrl('javascript:alert(1)');
|
||||
ci.ctxProp = trusted;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().getProperty(e, 'href')).toEqual('javascript:alert(1)');
|
||||
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
|
||||
itAsync(
|
||||
'should error when using the wrong trusted value',
|
||||
[TestComponentBuilder, AsyncTestCompleter, DomSanitizationService],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter,
|
||||
sanitizer: DomSanitizationService) => {
|
||||
let tpl = `<a [href]="ctxProp">Link Title</a>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should error when using the wrong trusted value', () => {
|
||||
const template = `<a [href]="ctxProp">Link Title</a>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
const sanitizer: DomSanitizationService = getTestBed().get(DomSanitizationService);
|
||||
|
||||
let trusted = sanitizer.bypassSecurityTrustScript('javascript:alert(1)');
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
ci.ctxProp = trusted;
|
||||
expect(() => fixture.detectChanges())
|
||||
.toThrowError(/Required a safe URL, got a Script/);
|
||||
|
||||
async.done();
|
||||
});
|
||||
expect(() => fixture.detectChanges()).toThrowError(/Required a safe URL, got a Script/);
|
||||
});
|
||||
|
||||
itAsync(
|
||||
'should warn when using in string interpolation',
|
||||
[TestComponentBuilder, AsyncTestCompleter, DomSanitizationService],
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter,
|
||||
sanitizer: DomSanitizationService) => {
|
||||
let tpl = `<a href="/foo/{{ctxProp}}">Link Title</a>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should warn when using in string interpolation', () => {
|
||||
const template = `<a href="/foo/{{ctxProp}}">Link Title</a>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
const sanitizer: DomSanitizationService = getTestBed().get(DomSanitizationService);
|
||||
|
||||
let e = fixture.debugElement.children[0].nativeElement;
|
||||
let trusted = sanitizer.bypassSecurityTrustUrl('bar/baz');
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
ci.ctxProp = trusted;
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().getProperty(e, 'href')).toMatch(/SafeValue(%20| )must(%20| )use/);
|
||||
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('sanitizing', () => {
|
||||
itAsync(
|
||||
'should escape unsafe attributes',
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
let tpl = `<a [href]="ctxProp">Link Title</a>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should escape unsafe attributes', () => {
|
||||
const template = `<a [href]="ctxProp">Link Title</a>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
|
||||
let e = fixture.debugElement.children[0].nativeElement;
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
ci.ctxProp = 'hello';
|
||||
@ -148,18 +113,13 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
ci.ctxProp = 'javascript:alert(1)';
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().getProperty(e, 'href')).toEqual('unsafe:javascript:alert(1)');
|
||||
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
|
||||
itAsync(
|
||||
'should escape unsafe style values',
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
let tpl = `<div [style.background]="ctxProp">Text</div>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should escape unsafe style values', () => {
|
||||
const template = `<div [style.background]="ctxProp">Text</div>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
|
||||
let e = fixture.debugElement.children[0].nativeElement;
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
// Make sure binding harmless values works.
|
||||
@ -173,32 +133,25 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
fixture.detectChanges();
|
||||
// Updated value gets rejected, no value change.
|
||||
expect(getDOM().getStyle(e, 'background')).not.toContain('javascript');
|
||||
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
|
||||
itAsync(
|
||||
'should escape unsafe SVG attributes',
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
let tpl = `<svg:circle [xlink:href]="ctxProp">Text</svg:circle>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then(v => async.done(new Error('unexpected success')))
|
||||
.catch((e) => {
|
||||
it('should escape unsafe SVG attributes', () => {
|
||||
const template = `<svg:circle [xlink:href]="ctxProp">Text</svg:circle>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
|
||||
try {
|
||||
TestBed.createComponent(SecuredComponent);
|
||||
throw 'Should throw';
|
||||
} catch (e) {
|
||||
expect(e.message).toContain(`Can't bind to 'xlink:href'`);
|
||||
async.done();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
itAsync(
|
||||
'should escape unsafe HTML values',
|
||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
||||
let tpl = `<div [innerHTML]="ctxProp">Text</div>`;
|
||||
tcb.overrideTemplate(SecuredComponent, tpl)
|
||||
.createAsync(SecuredComponent)
|
||||
.then((fixture) => {
|
||||
it('should escape unsafe HTML values', () => {
|
||||
const template = `<div [innerHTML]="ctxProp">Text</div>`;
|
||||
TestBed.overrideComponent(SecuredComponent, {set: {template}});
|
||||
const fixture = TestBed.createComponent(SecuredComponent);
|
||||
|
||||
let e = fixture.debugElement.children[0].nativeElement;
|
||||
let ci = fixture.debugElement.componentInstance;
|
||||
// Make sure binding harmless values works.
|
||||
@ -217,9 +170,6 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
ci.ctxProp = 'also <iframe srcdoc="evil"></iframe> evil';
|
||||
fixture.detectChanges();
|
||||
expect(getDOM().getInnerHTML(e)).toEqual('also evil');
|
||||
|
||||
async.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -9,63 +9,19 @@
|
||||
import {NgFor, NgIf} from '@angular/common';
|
||||
import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, DebugElement, Directive, ElementRef, Host, Inject, InjectMetadata, Input, Optional, Pipe, PipeTransform, Self, SkipSelfMetadata, TemplateRef, Type, ViewContainerRef, forwardRef} from '@angular/core';
|
||||
import {ViewMetadata} from '@angular/core/src/metadata/view';
|
||||
import {ComponentFixture, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
||||
import {TestComponentBuilder, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
|
||||
import {ComponentFixture, TestBed, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
||||
import {beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
|
||||
import {isBlank} from '../../src/facade/lang';
|
||||
|
||||
const ALL_DIRECTIVES = [
|
||||
forwardRef(() => SimpleDirective),
|
||||
forwardRef(() => CycleDirective),
|
||||
forwardRef(() => SimpleComponent),
|
||||
forwardRef(() => SomeOtherDirective),
|
||||
forwardRef(() => NeedsDirectiveFromSelf),
|
||||
forwardRef(() => NeedsServiceComponent),
|
||||
forwardRef(() => OptionallyNeedsDirective),
|
||||
forwardRef(() => NeedsComponentFromHost),
|
||||
forwardRef(() => NeedsDirectiveFromHost),
|
||||
forwardRef(() => NeedsDirective),
|
||||
forwardRef(() => NeedsService),
|
||||
forwardRef(() => NeedsAppService),
|
||||
forwardRef(() => NeedsAttribute),
|
||||
forwardRef(() => NeedsAttributeNoType),
|
||||
forwardRef(() => NeedsElementRef),
|
||||
forwardRef(() => NeedsViewContainerRef),
|
||||
forwardRef(() => NeedsTemplateRef),
|
||||
forwardRef(() => OptionallyNeedsTemplateRef),
|
||||
forwardRef(() => DirectiveNeedsChangeDetectorRef),
|
||||
forwardRef(() => PushComponentNeedsChangeDetectorRef),
|
||||
forwardRef(() => NeedsServiceFromHost),
|
||||
forwardRef(() => NeedsAttribute),
|
||||
forwardRef(() => NeedsAttributeNoType),
|
||||
forwardRef(() => NeedsElementRef),
|
||||
forwardRef(() => NeedsViewContainerRef),
|
||||
forwardRef(() => NeedsTemplateRef),
|
||||
forwardRef(() => OptionallyNeedsTemplateRef),
|
||||
forwardRef(() => DirectiveNeedsChangeDetectorRef),
|
||||
forwardRef(() => PushComponentNeedsChangeDetectorRef),
|
||||
forwardRef(() => NeedsHostAppService),
|
||||
NgIf,
|
||||
NgFor
|
||||
];
|
||||
|
||||
const ALL_PIPES = [
|
||||
forwardRef(() => PipeNeedsChangeDetectorRef),
|
||||
forwardRef(() => PipeNeedsService),
|
||||
forwardRef(() => PurePipe),
|
||||
forwardRef(() => ImpurePipe),
|
||||
forwardRef(() => DuplicatePipe1),
|
||||
forwardRef(() => DuplicatePipe2),
|
||||
];
|
||||
|
||||
@Directive({selector: '[simpleDirective]'})
|
||||
class SimpleDirective {
|
||||
@Input('simpleDirective') value: any = null;
|
||||
}
|
||||
|
||||
@Component({selector: '[simpleComponent]', template: '', directives: ALL_DIRECTIVES})
|
||||
@Component({selector: '[simpleComponent]', template: ''})
|
||||
class SimpleComponent {
|
||||
}
|
||||
|
||||
@ -111,40 +67,38 @@ class NeedsDirective {
|
||||
@Directive({selector: '[needsService]'})
|
||||
class NeedsService {
|
||||
service: any;
|
||||
constructor(@Inject('service') service: any /** TODO #9100 */) { this.service = service; }
|
||||
constructor(@Inject('service') service: any) { this.service = service; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsAppService]'})
|
||||
class NeedsAppService {
|
||||
service: any;
|
||||
constructor(@Inject('appService') service: any /** TODO #9100 */) { this.service = service; }
|
||||
constructor(@Inject('appService') service: any) { this.service = service; }
|
||||
}
|
||||
|
||||
@Component({selector: '[needsHostAppService]', template: '', directives: ALL_DIRECTIVES})
|
||||
@Component({selector: '[needsHostAppService]', template: ''})
|
||||
class NeedsHostAppService {
|
||||
service: any;
|
||||
constructor(@Host() @Inject('appService') service: any /** TODO #9100 */) {
|
||||
this.service = service;
|
||||
}
|
||||
constructor(@Host() @Inject('appService') service: any) { this.service = service; }
|
||||
}
|
||||
|
||||
@Component({selector: '[needsServiceComponent]', template: ''})
|
||||
class NeedsServiceComponent {
|
||||
service: any;
|
||||
constructor(@Inject('service') service: any /** TODO #9100 */) { this.service = service; }
|
||||
constructor(@Inject('service') service: any) { this.service = service; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsServiceFromHost]'})
|
||||
class NeedsServiceFromHost {
|
||||
service: any;
|
||||
constructor(@Host() @Inject('service') service: any /** TODO #9100 */) { this.service = service; }
|
||||
constructor(@Host() @Inject('service') service: any) { this.service = service; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsAttribute]'})
|
||||
class NeedsAttribute {
|
||||
typeAttribute: any /** TODO #9100 */;
|
||||
titleAttribute: any /** TODO #9100 */;
|
||||
fooAttribute: any /** TODO #9100 */;
|
||||
typeAttribute: any;
|
||||
titleAttribute: any;
|
||||
fooAttribute: any;
|
||||
constructor(
|
||||
@Attribute('type') typeAttribute: String, @Attribute('title') titleAttribute: String,
|
||||
@Attribute('foo') fooAttribute: String) {
|
||||
@ -156,33 +110,31 @@ class NeedsAttribute {
|
||||
|
||||
@Directive({selector: '[needsAttributeNoType]'})
|
||||
class NeedsAttributeNoType {
|
||||
fooAttribute: any /** TODO #9100 */;
|
||||
constructor(@Attribute('foo') fooAttribute: any /** TODO #9100 */) {
|
||||
this.fooAttribute = fooAttribute;
|
||||
}
|
||||
fooAttribute: any;
|
||||
constructor(@Attribute('foo') fooAttribute: any) { this.fooAttribute = fooAttribute; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsElementRef]'})
|
||||
class NeedsElementRef {
|
||||
elementRef: any /** TODO #9100 */;
|
||||
elementRef: any;
|
||||
constructor(ref: ElementRef) { this.elementRef = ref; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsViewContainerRef]'})
|
||||
class NeedsViewContainerRef {
|
||||
viewContainer: any /** TODO #9100 */;
|
||||
viewContainer: any;
|
||||
constructor(vc: ViewContainerRef) { this.viewContainer = vc; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[needsTemplateRef]'})
|
||||
class NeedsTemplateRef {
|
||||
templateRef: any /** TODO #9100 */;
|
||||
templateRef: any;
|
||||
constructor(ref: TemplateRef<Object>) { this.templateRef = ref; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[optionallyNeedsTemplateRef]'})
|
||||
class OptionallyNeedsTemplateRef {
|
||||
templateRef: any /** TODO #9100 */;
|
||||
templateRef: any;
|
||||
constructor(@Optional() ref: TemplateRef<Object>) { this.templateRef = ref; }
|
||||
}
|
||||
|
||||
@ -194,7 +146,6 @@ class DirectiveNeedsChangeDetectorRef {
|
||||
@Component({
|
||||
selector: '[componentNeedsChangeDetectorRef]',
|
||||
template: '{{counter}}',
|
||||
directives: ALL_DIRECTIVES,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
class PushComponentNeedsChangeDetectorRef {
|
||||
@ -223,7 +174,7 @@ class PipeNeedsChangeDetectorRef {
|
||||
@Pipe({name: 'pipeNeedsService'})
|
||||
export class PipeNeedsService implements PipeTransform {
|
||||
service: any;
|
||||
constructor(@Inject('service') service: any /** TODO #9100 */) { this.service = service; }
|
||||
constructor(@Inject('service') service: any) { this.service = service; }
|
||||
transform(value: any): any { return this; }
|
||||
}
|
||||
|
||||
@ -237,58 +188,57 @@ export class DuplicatePipe2 implements PipeTransform {
|
||||
transform(value: any): any { return this; }
|
||||
}
|
||||
|
||||
@Component({selector: 'root'})
|
||||
@Component({selector: 'root', template: ''})
|
||||
class TestComp {
|
||||
}
|
||||
|
||||
export function main() {
|
||||
var tcb: TestComponentBuilder;
|
||||
|
||||
function createCompFixture<T>(
|
||||
template: string, tcb: TestComponentBuilder, comp: Type<T> = null): ComponentFixture<T> {
|
||||
if (isBlank(comp)) {
|
||||
function createComponentFixture<T>(
|
||||
template: string, providers: any[] = null, comp: Type<T> = null): ComponentFixture<T> {
|
||||
if (!comp) {
|
||||
comp = <any>TestComp;
|
||||
}
|
||||
return tcb
|
||||
.overrideView(
|
||||
comp,
|
||||
new ViewMetadata({template: template, directives: ALL_DIRECTIVES, pipes: ALL_PIPES}))
|
||||
.createFakeAsync(comp);
|
||||
TestBed.overrideComponent(comp, {set: {template}});
|
||||
if (providers && providers.length) {
|
||||
TestBed.overrideComponent(comp, {add: {providers: providers}});
|
||||
}
|
||||
return TestBed.createComponent(comp);
|
||||
}
|
||||
|
||||
function createComp(
|
||||
template: string, tcb: TestComponentBuilder, comp: Type<any> = null): DebugElement {
|
||||
var fixture = createCompFixture(template, tcb, comp);
|
||||
function createComponent(
|
||||
template: string, providers: any[] = null, comp: Type<any> = null): DebugElement {
|
||||
const fixture = createComponentFixture(template, providers, comp);
|
||||
fixture.detectChanges();
|
||||
return fixture.debugElement;
|
||||
}
|
||||
|
||||
describe('View Injector', () => {
|
||||
describe('View injector', () => {
|
||||
// On CJS fakeAsync is not supported...
|
||||
if (!getDOM().supportsDOMEvents()) return;
|
||||
|
||||
beforeEach(() => TestBed.configureTestingModule({declarations: [TestComp]}));
|
||||
|
||||
beforeEachProviders(() => [{provide: 'appService', useValue: 'appService'}]);
|
||||
|
||||
beforeEach(
|
||||
fakeAsync(inject([TestComponentBuilder], (_tcb: TestComponentBuilder) => { tcb = _tcb; })));
|
||||
|
||||
describe('injection', () => {
|
||||
it('should instantiate directives that have no dependencies', fakeAsync(() => {
|
||||
var el = createComp('<div simpleDirective>', tcb);
|
||||
it('should instantiate directives that have no dependencies', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
const el = createComponent('<div simpleDirective>');
|
||||
expect(el.children[0].injector.get(SimpleDirective)).toBeAnInstanceOf(SimpleDirective);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on another directive', fakeAsync(() => {
|
||||
var el = createComp('<div simpleDirective needsDirective>', tcb);
|
||||
it('should instantiate directives that depend on another directive', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsDirective]});
|
||||
const el = createComponent('<div simpleDirective needsDirective>');
|
||||
|
||||
var d = el.children[0].injector.get(NeedsDirective);
|
||||
|
||||
expect(d).toBeAnInstanceOf(NeedsDirective);
|
||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should support useValue with different values', fakeAsync(() => {
|
||||
var el = createComp('', tcb.overrideProviders(TestComp, [
|
||||
it('should support useValue with different values', () => {
|
||||
const el = createComponent('', [
|
||||
{provide: 'numLiteral', useValue: 0},
|
||||
{provide: 'boolLiteral', useValue: true},
|
||||
{provide: 'strLiteral', useValue: 'a'},
|
||||
@ -297,7 +247,7 @@ export function main() {
|
||||
{provide: 'map', useValue: {'a': 1}},
|
||||
{provide: 'instance', useValue: new TestValue('a')},
|
||||
{provide: 'nested', useValue: [{'a': [1]}, new TestValue('b')]},
|
||||
]));
|
||||
]);
|
||||
expect(el.injector.get('numLiteral')).toBe(0);
|
||||
expect(el.injector.get('boolLiteral')).toBe(true);
|
||||
expect(el.injector.get('strLiteral')).toBe('a');
|
||||
@ -306,424 +256,475 @@ export function main() {
|
||||
expect(el.injector.get('map')).toEqual({'a': 1});
|
||||
expect(el.injector.get('instance')).toEqual(new TestValue('a'));
|
||||
expect(el.injector.get('nested')).toEqual([{'a': [1]}, new TestValue('b')]);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate providers that have dependencies with SkipSelf', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleDirective><span someOtherDirective></span></div>',
|
||||
tcb.overrideProviders(
|
||||
SimpleDirective, [{provide: 'injectable1', useValue: 'injectable1'}])
|
||||
.overrideProviders(SomeOtherDirective, [
|
||||
it('should instantiate providers that have dependencies with SkipSelf', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, SomeOtherDirective]});
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective,
|
||||
{add: {providers: [{provide: 'injectable1', useValue: 'injectable1'}]}});
|
||||
TestBed.overrideDirective(SomeOtherDirective, {
|
||||
add: {
|
||||
providers: [
|
||||
{provide: 'injectable1', useValue: 'new-injectable1'}, {
|
||||
provide: 'injectable2',
|
||||
useFactory: (val: any /** TODO #9100 */) => `${val}-injectable2`,
|
||||
useFactory: (val: any) => `${val}-injectable2`,
|
||||
deps: [[new InjectMetadata('injectable1'), new SkipSelfMetadata()]]
|
||||
}
|
||||
]));
|
||||
]
|
||||
}
|
||||
});
|
||||
const el = createComponent('<div simpleDirective><span someOtherDirective></span></div>');
|
||||
expect(el.children[0].children[0].injector.get('injectable2'))
|
||||
.toEqual('injectable1-injectable2');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate providers that have dependencies', fakeAsync(() => {
|
||||
var providers = [
|
||||
it('should instantiate providers that have dependencies', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
const providers = [
|
||||
{provide: 'injectable1', useValue: 'injectable1'}, {
|
||||
provide: 'injectable2',
|
||||
useFactory: (val: any /** TODO #9100 */) => `${val}-injectable2`,
|
||||
useFactory: (val: any) => `${val}-injectable2`,
|
||||
deps: ['injectable1']
|
||||
}
|
||||
];
|
||||
var el = createComp(
|
||||
'<div simpleDirective></div>', tcb.overrideProviders(SimpleDirective, providers));
|
||||
TestBed.overrideDirective(SimpleDirective, {add: {providers}});
|
||||
var el = createComponent('<div simpleDirective></div>');
|
||||
expect(el.children[0].injector.get('injectable2')).toEqual('injectable1-injectable2');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate viewProviders that have dependencies', fakeAsync(() => {
|
||||
var viewProviders = [
|
||||
it('should instantiate viewProviders that have dependencies', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent]});
|
||||
const viewProviders = [
|
||||
{provide: 'injectable1', useValue: 'injectable1'}, {
|
||||
provide: 'injectable2',
|
||||
useFactory: (val: any /** TODO #9100 */) => `${val}-injectable2`,
|
||||
useFactory: (val: any) => `${val}-injectable2`,
|
||||
deps: ['injectable1']
|
||||
}
|
||||
];
|
||||
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideViewProviders(SimpleComponent, viewProviders));
|
||||
TestBed.overrideComponent(SimpleComponent, {set: {viewProviders}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
expect(el.children[0].injector.get('injectable2')).toEqual('injectable1-injectable2');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate components that depend on viewProviders providers', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div needsServiceComponent></div>',
|
||||
tcb.overrideViewProviders(
|
||||
NeedsServiceComponent, [{provide: 'service', useValue: 'service'}]));
|
||||
it('should instantiate components that depend on viewProviders providers', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsServiceComponent]});
|
||||
TestBed.overrideComponent(
|
||||
NeedsServiceComponent, {set: {providers: [{provide: 'service', useValue: 'service'}]}});
|
||||
const el = createComponent('<div needsServiceComponent></div>');
|
||||
expect(el.children[0].injector.get(NeedsServiceComponent).service).toEqual('service');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate multi providers', fakeAsync(() => {
|
||||
var providers = [
|
||||
it('should instantiate multi providers', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
const providers = [
|
||||
{provide: 'injectable1', useValue: 'injectable11', multi: true},
|
||||
{provide: 'injectable1', useValue: 'injectable12', multi: true}
|
||||
];
|
||||
var el = createComp(
|
||||
'<div simpleDirective></div>', tcb.overrideProviders(SimpleDirective, providers));
|
||||
TestBed.overrideDirective(SimpleDirective, {set: {providers}});
|
||||
const el = createComponent('<div simpleDirective></div>');
|
||||
expect(el.children[0].injector.get('injectable1')).toEqual([
|
||||
'injectable11', 'injectable12'
|
||||
]);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate providers lazily', fakeAsync(() => {
|
||||
var created = false;
|
||||
var el = createComp(
|
||||
'<div simpleDirective></div>',
|
||||
tcb.overrideProviders(
|
||||
SimpleDirective, [{provide: 'service', useFactory: () => created = true}]));
|
||||
it('should instantiate providers lazily', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
|
||||
let created = false;
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective,
|
||||
{set: {providers: [{provide: 'service', useFactory: () => created = true}]}});
|
||||
const el = createComponent('<div simpleDirective></div>');
|
||||
|
||||
expect(created).toBe(false);
|
||||
|
||||
el.children[0].injector.get('service');
|
||||
|
||||
expect(created).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate providers with a lifecycle hook eagerly', fakeAsync(() => {
|
||||
var created = false;
|
||||
it('should instantiate providers lazily', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
let created = false;
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective,
|
||||
{set: {providers: [{provide: 'service', useFactory: () => created = true}]}});
|
||||
|
||||
const el = createComponent('<div simpleDirective></div>');
|
||||
|
||||
expect(created).toBe(false);
|
||||
|
||||
el.children[0].injector.get('service');
|
||||
|
||||
expect(created).toBe(true);
|
||||
});
|
||||
|
||||
it('should instantiate providers with a lifecycle hook eagerly', () => {
|
||||
let created = false;
|
||||
class SomeInjectable {
|
||||
constructor() { created = true; }
|
||||
ngOnDestroy() {}
|
||||
}
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective]});
|
||||
TestBed.overrideDirective(SimpleDirective, {set: {providers: [SomeInjectable]}});
|
||||
|
||||
var el = createComp(
|
||||
'<div simpleDirective></div>',
|
||||
tcb.overrideProviders(SimpleDirective, [SomeInjectable]));
|
||||
const el = createComponent('<div simpleDirective></div>');
|
||||
|
||||
expect(created).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate view providers lazily', fakeAsync(() => {
|
||||
var created = false;
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideViewProviders(
|
||||
SimpleComponent, [{provide: 'service', useFactory: () => created = true}]));
|
||||
it('should instantiate view providers lazily', () => {
|
||||
let created = false;
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {viewProviders: [{provide: 'service', useFactory: () => created = true}]}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
|
||||
expect(created).toBe(false);
|
||||
|
||||
el.children[0].injector.get('service');
|
||||
|
||||
expect(created).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate other directives that depend on viewProviders providers (same element)',
|
||||
fakeAsync(() => {
|
||||
expect(
|
||||
() => createComp(
|
||||
'<div simpleComponent needsService></div>',
|
||||
tcb.overrideViewProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'service'}])))
|
||||
() => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {viewProviders: [{provide: 'service', useValue: 'service'}]}});
|
||||
expect(() => createComponent('<div simpleComponent needsService></div>'))
|
||||
.toThrowError(/No provider for service!/);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate other directives that depend on viewProviders providers (child element)',
|
||||
fakeAsync(() => {
|
||||
expect(
|
||||
() => createComp(
|
||||
'<div simpleComponent><div needsService></div></div>',
|
||||
tcb.overrideViewProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'service'}])))
|
||||
() => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {viewProviders: [{provide: 'service', useValue: 'service'}]}});
|
||||
expect(() => createComponent('<div simpleComponent><div needsService></div></div>'))
|
||||
.toThrowError(/No provider for service!/);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on providers of other directives',
|
||||
fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleDirective><div needsService></div></div>',
|
||||
tcb.overrideProviders(
|
||||
SimpleDirective, [{provide: 'service', useValue: 'parentService'}]));
|
||||
it('should instantiate directives that depend on providers of other directives', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsService]});
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective, {set: {providers: [{provide: 'service', useValue: 'parentService'}]}});
|
||||
|
||||
const el = createComponent('<div simpleDirective><div needsService></div></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('parentService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on providers in a parent view',
|
||||
fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleDirective><template [ngIf]="true"><div *ngIf="true" needsService></div></template></div>',
|
||||
tcb.overrideProviders(
|
||||
SimpleDirective, [{provide: 'service', useValue: 'parentService'}]));
|
||||
it('should instantiate directives that depend on providers in a parent view', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsService]});
|
||||
TestBed.overrideDirective(
|
||||
SimpleDirective, {set: {providers: [{provide: 'service', useValue: 'parentService'}]}});
|
||||
const el = createComponent(
|
||||
'<div simpleDirective><template [ngIf]="true"><div *ngIf="true" needsService></div></template></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('parentService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on providers of a component', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideTemplate(SimpleComponent, '<div needsService></div>')
|
||||
.overrideProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'hostService'}]));
|
||||
it('should instantiate directives that depend on providers of a component', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {providers: [{provide: 'service', useValue: 'hostService'}]}});
|
||||
TestBed.overrideComponent(SimpleComponent, {set: {template: '<div needsService></div>'}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('hostService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on view providers of a component',
|
||||
fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideTemplate(SimpleComponent, '<div needsService></div>')
|
||||
.overrideViewProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'hostService'}]));
|
||||
it('should instantiate directives that depend on view providers of a component', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {providers: [{provide: 'service', useValue: 'hostService'}]}});
|
||||
TestBed.overrideComponent(SimpleComponent, {set: {template: '<div needsService></div>'}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('hostService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives in a root embedded view that depend on view providers of a component',
|
||||
fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideTemplate(SimpleComponent, '<div *ngIf="true" needsService></div>')
|
||||
.overrideViewProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'hostService'}]));
|
||||
() => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {providers: [{provide: 'service', useValue: 'hostService'}]}});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {template: '<div *ngIf="true" needsService></div>'}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
expect(el.children[0].children[0].injector.get(NeedsService).service)
|
||||
.toEqual('hostService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on instances in the app injector',
|
||||
fakeAsync(() => {
|
||||
var el = createComp('<div needsAppService></div>', tcb);
|
||||
it('should instantiate directives that depend on instances in the app injector', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsAppService]});
|
||||
const el = createComponent('<div needsAppService></div>');
|
||||
expect(el.children[0].injector.get(NeedsAppService).service).toEqual('appService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate a directive with cyclic dependencies', fakeAsync(() => {
|
||||
expect(() => createComp('<div cycleDirective></div>', tcb))
|
||||
it('should not instantiate a directive with cyclic dependencies', () => {
|
||||
TestBed.configureTestingModule({declarations: [CycleDirective]});
|
||||
expect(() => createComponent('<div cycleDirective></div>'))
|
||||
.toThrowError(
|
||||
'Template parse errors:\nCannot instantiate cyclic dependency! CycleDirective ("[ERROR ->]<div cycleDirective></div>"): TestComp@0:0');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate a directive in a view that has a host dependency on providers' +
|
||||
' of the component',
|
||||
fakeAsync(() => {
|
||||
expect(
|
||||
() => createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideProviders(
|
||||
SimpleComponent, [{provide: 'service', useValue: 'hostService'}])
|
||||
.overrideTemplate(SimpleComponent, '<div needsServiceFromHost><div>')))
|
||||
() => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsServiceFromHost]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {providers: [{provide: 'service', useValue: 'hostService'}]}});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {template: '<div needsServiceFromHost><div>'}});
|
||||
|
||||
expect(() => createComponent('<div simpleComponent></div>'))
|
||||
.toThrowError(
|
||||
`Template parse errors:\nNo provider for service ("[ERROR ->]<div needsServiceFromHost><div>"): SimpleComponent@0:0`);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate a directive in a view that has a host dependency on providers' +
|
||||
' of a decorator directive',
|
||||
fakeAsync(() => {
|
||||
expect(
|
||||
() => createComp(
|
||||
'<div simpleComponent someOtherDirective></div>',
|
||||
tcb.overrideProviders(
|
||||
SomeOtherDirective, [{provide: 'service', useValue: 'hostService'}])
|
||||
.overrideTemplate(SimpleComponent, '<div needsServiceFromHost><div>')))
|
||||
() => {
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent,
|
||||
{set: {providers: [{provide: 'service', useValue: 'hostService'}]}});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {template: '<div needsServiceFromHost><div>'}});
|
||||
|
||||
expect(() => createComponent('<div simpleComponent someOtherDirective></div>'))
|
||||
.toThrowError(
|
||||
`Template parse errors:\nNo provider for service ("[ERROR ->]<div needsServiceFromHost><div>"): SimpleComponent@0:0`);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate a directive in a view that has a self dependency on a parent directive',
|
||||
fakeAsync(() => {
|
||||
() => {
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [SimpleDirective, NeedsDirectiveFromSelf]});
|
||||
expect(
|
||||
() =>
|
||||
createComp('<div simpleDirective><div needsDirectiveFromSelf></div></div>', tcb))
|
||||
createComponent('<div simpleDirective><div needsDirectiveFromSelf></div></div>'))
|
||||
.toThrowError(
|
||||
`Template parse errors:\nNo provider for SimpleDirective ("<div simpleDirective>[ERROR ->]<div needsDirectiveFromSelf></div></div>"): TestComp@0:21`);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depend on other directives', fakeAsync(() => {
|
||||
var el = createComp('<div simpleDirective><div needsDirective></div></div>', tcb);
|
||||
var d = el.children[0].children[0].injector.get(NeedsDirective);
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsDirective]});
|
||||
const el = createComponent('<div simpleDirective><div needsDirective></div></div>');
|
||||
const d = el.children[0].children[0].injector.get(NeedsDirective);
|
||||
|
||||
expect(d).toBeAnInstanceOf(NeedsDirective);
|
||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||
}));
|
||||
|
||||
it('should throw when a dependency cannot be resolved', fakeAsync(() => {
|
||||
expect(() => createComp('<div needsService></div>', tcb))
|
||||
TestBed.configureTestingModule({declarations: [NeedsService]});
|
||||
|
||||
expect(() => createComponent('<div needsService></div>'))
|
||||
.toThrowError(/No provider for service!/);
|
||||
}));
|
||||
|
||||
it('should inject null when an optional dependency cannot be resolved', fakeAsync(() => {
|
||||
var el = createComp('<div optionallyNeedsDirective></div>', tcb);
|
||||
var d = el.children[0].injector.get(OptionallyNeedsDirective);
|
||||
it('should inject null when an optional dependency cannot be resolved', () => {
|
||||
TestBed.configureTestingModule({declarations: [OptionallyNeedsDirective]});
|
||||
const el = createComponent('<div optionallyNeedsDirective></div>');
|
||||
const d = el.children[0].injector.get(OptionallyNeedsDirective);
|
||||
expect(d.dependency).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate directives that depends on the host component', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div simpleComponent></div>',
|
||||
tcb.overrideTemplate(SimpleComponent, '<div needsComponentFromHost></div>'));
|
||||
var d = el.children[0].children[0].injector.get(NeedsComponentFromHost);
|
||||
it('should instantiate directives that depends on the host component', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsComponentFromHost]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {template: '<div needsComponentFromHost></div>'}});
|
||||
const el = createComponent('<div simpleComponent></div>');
|
||||
const d = el.children[0].children[0].injector.get(NeedsComponentFromHost);
|
||||
expect(d.dependency).toBeAnInstanceOf(SimpleComponent);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should instantiate host views for components that have a @Host dependency ',
|
||||
fakeAsync(() => {
|
||||
var el = createComp('', tcb, NeedsHostAppService);
|
||||
it('should instantiate host views for components that have a @Host dependency ', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsHostAppService]});
|
||||
const el = createComponent('', [], NeedsHostAppService);
|
||||
expect(el.componentInstance.service).toEqual('appService');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not instantiate directives that depend on other directives on the host element',
|
||||
fakeAsync(() => {
|
||||
expect(
|
||||
() => createComp(
|
||||
'<div simpleComponent simpleDirective></div>',
|
||||
tcb.overrideTemplate(SimpleComponent, '<div needsDirectiveFromHost></div>')))
|
||||
it('should not instantiate directives that depend on other directives on the host element', () => {
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]});
|
||||
TestBed.overrideComponent(
|
||||
SimpleComponent, {set: {template: '<div needsDirectiveFromHost></div>'}});
|
||||
expect(() => createComponent('<div simpleComponent simpleDirective></div>'))
|
||||
.toThrowError(
|
||||
`Template parse errors:\nNo provider for SimpleDirective ("[ERROR ->]<div needsDirectiveFromHost></div>"): SimpleComponent@0:0`);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('static attributes', () => {
|
||||
it('should be injectable', fakeAsync(() => {
|
||||
var el = createComp('<div needsAttribute type="text" title></div>', tcb);
|
||||
var needsAttribute = el.children[0].injector.get(NeedsAttribute);
|
||||
it('should be injectable', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsAttribute]});
|
||||
const el = createComponent('<div needsAttribute type="text" title></div>');
|
||||
const needsAttribute = el.children[0].injector.get(NeedsAttribute);
|
||||
|
||||
expect(needsAttribute.typeAttribute).toEqual('text');
|
||||
expect(needsAttribute.titleAttribute).toEqual('');
|
||||
expect(needsAttribute.fooAttribute).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should be injectable without type annotation', fakeAsync(() => {
|
||||
var el = createComp('<div needsAttributeNoType foo="bar"></div>', tcb);
|
||||
var needsAttribute = el.children[0].injector.get(NeedsAttributeNoType);
|
||||
it('should be injectable without type annotation', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsAttributeNoType]});
|
||||
const el = createComponent('<div needsAttributeNoType foo="bar"></div>');
|
||||
const needsAttribute = el.children[0].injector.get(NeedsAttributeNoType);
|
||||
|
||||
expect(needsAttribute.fooAttribute).toEqual('bar');
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('refs', () => {
|
||||
it('should inject ElementRef', fakeAsync(() => {
|
||||
var el = createComp('<div needsElementRef></div>', tcb);
|
||||
it('should inject ElementRef', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsElementRef]});
|
||||
const el = createComponent('<div needsElementRef></div>');
|
||||
expect(el.children[0].injector.get(NeedsElementRef).elementRef.nativeElement)
|
||||
.toBe(el.children[0].nativeElement);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should inject ChangeDetectorRef of the component\'s view into the component via a proxy',
|
||||
fakeAsync(() => {
|
||||
var cf = createCompFixture('<div componentNeedsChangeDetectorRef></div>', tcb);
|
||||
() => {
|
||||
TestBed.configureTestingModule({declarations: [PushComponentNeedsChangeDetectorRef]});
|
||||
const cf = createComponentFixture('<div componentNeedsChangeDetectorRef></div>');
|
||||
cf.detectChanges();
|
||||
var compEl = cf.debugElement.children[0];
|
||||
var comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef);
|
||||
const compEl = cf.debugElement.children[0];
|
||||
const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef);
|
||||
comp.counter = 1;
|
||||
cf.detectChanges();
|
||||
expect(compEl.nativeElement).toHaveText('0');
|
||||
comp.changeDetectorRef.markForCheck();
|
||||
cf.detectChanges();
|
||||
expect(compEl.nativeElement).toHaveText('1');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should inject ChangeDetectorRef of the containing component into directives',
|
||||
fakeAsync(() => {
|
||||
var cf = createCompFixture(
|
||||
'<div componentNeedsChangeDetectorRef></div>',
|
||||
tcb.overrideTemplate(
|
||||
PushComponentNeedsChangeDetectorRef,
|
||||
'{{counter}}<div directiveNeedsChangeDetectorRef></div><div *ngIf="true" directiveNeedsChangeDetectorRef></div>'));
|
||||
it('should inject ChangeDetectorRef of the containing component into directives', () => {
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef]});
|
||||
TestBed.overrideComponent(PushComponentNeedsChangeDetectorRef, {
|
||||
set: {
|
||||
template:
|
||||
'{{counter}}<div directiveNeedsChangeDetectorRef></div><div *ngIf="true" directiveNeedsChangeDetectorRef></div>'
|
||||
}
|
||||
});
|
||||
const cf = createComponentFixture('<div componentNeedsChangeDetectorRef></div>');
|
||||
cf.detectChanges();
|
||||
var compEl = cf.debugElement.children[0];
|
||||
var comp: PushComponentNeedsChangeDetectorRef =
|
||||
const compEl = cf.debugElement.children[0];
|
||||
const comp: PushComponentNeedsChangeDetectorRef =
|
||||
compEl.injector.get(PushComponentNeedsChangeDetectorRef);
|
||||
comp.counter = 1;
|
||||
cf.detectChanges();
|
||||
expect(compEl.nativeElement).toHaveText('0');
|
||||
expect(
|
||||
compEl.children[0].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef)
|
||||
expect(compEl.children[0].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef)
|
||||
.toBe(comp.changeDetectorRef);
|
||||
expect(
|
||||
compEl.children[1].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef)
|
||||
expect(compEl.children[1].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef)
|
||||
.toBe(comp.changeDetectorRef);
|
||||
comp.changeDetectorRef.markForCheck();
|
||||
cf.detectChanges();
|
||||
expect(compEl.nativeElement).toHaveText('1');
|
||||
}));
|
||||
});
|
||||
|
||||
it('should inject ViewContainerRef', fakeAsync(() => {
|
||||
var el = createComp('<div needsViewContainerRef></div>', tcb);
|
||||
expect(el.children[0]
|
||||
.injector.get(NeedsViewContainerRef)
|
||||
.viewContainer.element.nativeElement)
|
||||
it('should inject ViewContainerRef', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsViewContainerRef]});
|
||||
const el = createComponent('<div needsViewContainerRef></div>');
|
||||
expect(
|
||||
el.children[0].injector.get(NeedsViewContainerRef).viewContainer.element.nativeElement)
|
||||
.toBe(el.children[0].nativeElement);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should inject TemplateRef', fakeAsync(() => {
|
||||
var el = createComp('<template needsViewContainerRef needsTemplateRef></template>', tcb);
|
||||
it('should inject TemplateRef', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsViewContainerRef, NeedsTemplateRef]});
|
||||
const el = createComponent('<template needsViewContainerRef needsTemplateRef></template>');
|
||||
expect(el.childNodes[0].injector.get(NeedsTemplateRef).templateRef.elementRef)
|
||||
.toEqual(el.childNodes[0].injector.get(NeedsViewContainerRef).viewContainer.element);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should throw if there is no TemplateRef', fakeAsync(() => {
|
||||
expect(() => createComp('<div needsTemplateRef></div>', tcb))
|
||||
it('should throw if there is no TemplateRef', () => {
|
||||
TestBed.configureTestingModule({declarations: [NeedsTemplateRef]});
|
||||
expect(() => createComponent('<div needsTemplateRef></div>'))
|
||||
.toThrowError(/No provider for TemplateRef!/);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should inject null if there is no TemplateRef when the dependency is optional',
|
||||
fakeAsync(() => {
|
||||
var el = createComp('<div optionallyNeedsTemplateRef></div>', tcb);
|
||||
var instance = el.children[0].injector.get(OptionallyNeedsTemplateRef);
|
||||
it('should inject null if there is no TemplateRef when the dependency is optional', () => {
|
||||
TestBed.configureTestingModule({declarations: [OptionallyNeedsTemplateRef]});
|
||||
const el = createComponent('<div optionallyNeedsTemplateRef></div>');
|
||||
const instance = el.children[0].injector.get(OptionallyNeedsTemplateRef);
|
||||
expect(instance.templateRef).toBeNull();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('pipes', () => {
|
||||
it('should instantiate pipes that have dependencies', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
it('should instantiate pipes that have dependencies', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, PipeNeedsService]});
|
||||
|
||||
const el = createComponent(
|
||||
'<div [simpleDirective]="true | pipeNeedsService"></div>',
|
||||
tcb.overrideProviders(TestComp, [{provide: 'service', useValue: 'pipeService'}]));
|
||||
expect(el.children[0].injector.get(SimpleDirective).value.service)
|
||||
.toEqual('pipeService');
|
||||
}));
|
||||
[{provide: 'service', useValue: 'pipeService'}]);
|
||||
expect(el.children[0].injector.get(SimpleDirective).value.service).toEqual('pipeService');
|
||||
});
|
||||
|
||||
it('should overwrite pipes with later entry in the pipes array', fakeAsync(() => {
|
||||
var el = createComp('<div [simpleDirective]="true | duplicatePipe"></div>', tcb);
|
||||
expect(el.children[0].injector.get(SimpleDirective).value)
|
||||
.toBeAnInstanceOf(DuplicatePipe2);
|
||||
}));
|
||||
it('should overwrite pipes with later entry in the pipes array', () => {
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [SimpleDirective, DuplicatePipe1, DuplicatePipe2]});
|
||||
const el = createComponent('<div [simpleDirective]="true | duplicatePipe"></div>');
|
||||
expect(el.children[0].injector.get(SimpleDirective).value).toBeAnInstanceOf(DuplicatePipe2);
|
||||
});
|
||||
|
||||
it('should inject ChangeDetectorRef into pipes', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
'<div [simpleDirective]="true | pipeNeedsChangeDetectorRef" directiveNeedsChangeDetectorRef></div>',
|
||||
tcb);
|
||||
var cdRef =
|
||||
it('should inject ChangeDetectorRef into pipes', () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations:
|
||||
[SimpleDirective, PipeNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef]
|
||||
});
|
||||
const el = createComponent(
|
||||
'<div [simpleDirective]="true | pipeNeedsChangeDetectorRef" directiveNeedsChangeDetectorRef></div>');
|
||||
const cdRef =
|
||||
el.children[0].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef;
|
||||
expect(el.children[0].injector.get(SimpleDirective).value.changeDetectorRef).toBe(cdRef);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should cache pure pipes', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
it('should cache pure pipes', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, PurePipe]});
|
||||
const el = createComponent(
|
||||
'<div [simpleDirective]="true | purePipe"></div><div [simpleDirective]="true | purePipe"></div>' +
|
||||
'<div *ngFor="let x of [1,2]" [simpleDirective]="true | purePipe"></div>',
|
||||
tcb);
|
||||
var purePipe1 = el.children[0].injector.get(SimpleDirective).value;
|
||||
var purePipe2 = el.children[1].injector.get(SimpleDirective).value;
|
||||
var purePipe3 = el.children[2].injector.get(SimpleDirective).value;
|
||||
var purePipe4 = el.children[3].injector.get(SimpleDirective).value;
|
||||
'<div *ngFor="let x of [1,2]" [simpleDirective]="true | purePipe"></div>');
|
||||
const purePipe1 = el.children[0].injector.get(SimpleDirective).value;
|
||||
const purePipe2 = el.children[1].injector.get(SimpleDirective).value;
|
||||
const purePipe3 = el.children[2].injector.get(SimpleDirective).value;
|
||||
const purePipe4 = el.children[3].injector.get(SimpleDirective).value;
|
||||
expect(purePipe1).toBeAnInstanceOf(PurePipe);
|
||||
expect(purePipe2).toBe(purePipe1);
|
||||
expect(purePipe3).toBe(purePipe1);
|
||||
expect(purePipe4).toBe(purePipe1);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not cache impure pipes', fakeAsync(() => {
|
||||
var el = createComp(
|
||||
it('should not cache impure pipes', () => {
|
||||
TestBed.configureTestingModule({declarations: [SimpleDirective, ImpurePipe]});
|
||||
const el = createComponent(
|
||||
'<div [simpleDirective]="true | impurePipe"></div><div [simpleDirective]="true | impurePipe"></div>' +
|
||||
'<div *ngFor="let x of [1,2]" [simpleDirective]="true | impurePipe"></div>',
|
||||
tcb);
|
||||
var purePipe1 = el.children[0].injector.get(SimpleDirective).value;
|
||||
var purePipe2 = el.children[1].injector.get(SimpleDirective).value;
|
||||
var purePipe3 = el.children[2].injector.get(SimpleDirective).value;
|
||||
var purePipe4 = el.children[3].injector.get(SimpleDirective).value;
|
||||
expect(purePipe1).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(purePipe2).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(purePipe2).not.toBe(purePipe1);
|
||||
expect(purePipe3).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(purePipe3).not.toBe(purePipe1);
|
||||
expect(purePipe4).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(purePipe4).not.toBe(purePipe1);
|
||||
}));
|
||||
'<div *ngFor="let x of [1,2]" [simpleDirective]="true | impurePipe"></div>');
|
||||
const impurePipe1 = el.children[0].injector.get(SimpleDirective).value;
|
||||
const impurePipe2 = el.children[1].injector.get(SimpleDirective).value;
|
||||
const impurePipe3 = el.children[2].injector.get(SimpleDirective).value;
|
||||
const impurePipe4 = el.children[3].injector.get(SimpleDirective).value;
|
||||
expect(impurePipe1).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(impurePipe2).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(impurePipe2).not.toBe(impurePipe1);
|
||||
expect(impurePipe3).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(impurePipe3).not.toBe(impurePipe1);
|
||||
expect(impurePipe4).toBeAnInstanceOf(ImpurePipe);
|
||||
expect(impurePipe4).not.toBe(impurePipe1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user