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:
Chuck Jazdzewski 2016-08-17 16:52:39 -07:00 committed by Kara
parent c48021ab97
commit a5c0349d88
4 changed files with 1128 additions and 1454 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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]}); });
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('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);
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('someCustomPipe');
});
});
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();
});
}));
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('red border');
});
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) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('true');
async.done();
});
}));
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);
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 => {
CountingPipe.reset();
fixture.detectChanges(/* checkNoChanges */ false);
expect(fixture.nativeElement).toHaveText('counting pipe value');
expect(CountingPipe.calls).toBe(1);
async.done();
});
}));
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('true');
});
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 => {
MyCountingComp.reset();
fixture.detectChanges(/* checkNoChanges */ false);
expect(fixture.nativeElement).toHaveText('counting method value');
expect(MyCountingComp.calls).toBe(1);
async.done();
});
}));
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);
});
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);
});
});
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) => {
var token = new OpaqueToken('a.b');
var tokenValue = 1;
createInjector(tcb, [
{provide: token, useValue: tokenValue}
]).then((injector: Injector) => {
expect(injector.get(token)).toEqual(tokenValue);
async.done();
});
}));
it('should support providers with an OpaqueToken that contains a `.` in the name', () => {
var token = new OpaqueToken('a.b');
var tokenValue = 1;
const injector = createInjector([{provide: token, useValue: tokenValue}]);
expect(injector.get(token)).toEqual(tokenValue);
});
it('should support providers with string token with a `.` in it',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var token = 'a.b';
var tokenValue = 1;
createInjector(tcb, [
{provide: token, useValue: tokenValue}
]).then((injector: Injector) => {
expect(injector.get(token)).toEqual(tokenValue);
async.done();
});
}));
it('should support providers with string token with a `.` in it', () => {
var token = 'a.b';
var tokenValue = 1;
const injector = createInjector([{provide: token, useValue: tokenValue}]);
it('should support providers with an anonymous function',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var token = () => true;
var tokenValue = 1;
createInjector(tcb, [
{provide: token, useValue: tokenValue}
]).then((injector: Injector) => {
expect(injector.get(token)).toEqual(tokenValue);
async.done();
});
}));
expect(injector.get(token)).toEqual(tokenValue);
});
it('should support providers with an OpaqueToken that has a StringMap as value',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
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) => {
expect(injector.get(token1)).toEqual(tokenValue1);
expect(injector.get(token2)).toEqual(tokenValue2);
async.done();
});
}));
it('should support providers with an anonymous function', () => {
var token = () => true;
var tokenValue = 1;
const injector = createInjector([{provide: token, useValue: tokenValue}]);
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};
const injector = createInjector(
[{provide: token1, useValue: tokenValue1}, {provide: token2, useValue: tokenValue2}]);
expect(injector.get(token1)).toEqual(tokenValue1);
expect(injector.get(token2)).toEqual(tokenValue2);
});
});
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) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('Class: a');
async.done();
});
}));
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);
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) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('ABC');
async.done();
});
}));
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('Class: a');
});
it('should handle mutual recursion entered from multiple sides - #7084',
inject(
[TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
tcb.createAsync(FakeRecursiveComp).then((fixture) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('[]');
async.done();
});
}));
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');
});
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('[]');
});
});
}
@ -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 {
}

View File

@ -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,175 +40,137 @@ 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) => {
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;
});
});
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)=... `);
}
});
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) => {
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)');
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);
async.done();
});
});
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)');
});
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) => {
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/);
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);
async.done();
});
});
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/);
});
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) => {
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/);
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);
async.done();
});
});
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/);
});
});
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) => {
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
ci.ctxProp = 'hello';
fixture.detectChanges();
// In the browser, reading href returns an absolute URL. On the server side,
// it just echoes back the property.
expect(getDOM().getProperty(e, 'href')).toMatch(/.*\/?hello$/);
it('should escape unsafe attributes', () => {
const template = `<a [href]="ctxProp">Link Title</a>`;
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
ci.ctxProp = 'javascript:alert(1)';
fixture.detectChanges();
expect(getDOM().getProperty(e, 'href')).toEqual('unsafe:javascript:alert(1)');
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
ci.ctxProp = 'hello';
fixture.detectChanges();
// In the browser, reading href returns an absolute URL. On the server side,
// it just echoes back the property.
expect(getDOM().getProperty(e, 'href')).toMatch(/.*\/?hello$/);
async.done();
});
});
ci.ctxProp = 'javascript:alert(1)';
fixture.detectChanges();
expect(getDOM().getProperty(e, 'href')).toEqual('unsafe:javascript:alert(1)');
});
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) => {
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
// Make sure binding harmless values works.
ci.ctxProp = 'red';
fixture.detectChanges();
// In some browsers, this will contain the full background specification, not just
// the color.
expect(getDOM().getStyle(e, 'background')).toMatch(/red.*/);
it('should escape unsafe style values', () => {
const template = `<div [style.background]="ctxProp">Text</div>`;
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
ci.ctxProp = 'url(javascript:evil())';
fixture.detectChanges();
// Updated value gets rejected, no value change.
expect(getDOM().getStyle(e, 'background')).not.toContain('javascript');
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
// Make sure binding harmless values works.
ci.ctxProp = 'red';
fixture.detectChanges();
// In some browsers, this will contain the full background specification, not just
// the color.
expect(getDOM().getStyle(e, 'background')).toMatch(/red.*/);
async.done();
});
});
ci.ctxProp = 'url(javascript:evil())';
fixture.detectChanges();
// Updated value gets rejected, no value change.
expect(getDOM().getStyle(e, 'background')).not.toContain('javascript');
});
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) => {
expect(e.message).toContain(`Can't bind to 'xlink:href'`);
async.done();
return null;
});
});
it('should escape unsafe SVG attributes', () => {
const template = `<svg:circle [xlink:href]="ctxProp">Text</svg:circle>`;
TestBed.overrideComponent(SecuredComponent, {set: {template}});
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) => {
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
// Make sure binding harmless values works.
ci.ctxProp = 'some <p>text</p>';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('some <p>text</p>');
try {
TestBed.createComponent(SecuredComponent);
throw 'Should throw';
} catch (e) {
expect(e.message).toContain(`Can't bind to 'xlink:href'`);
}
});
ci.ctxProp = 'ha <script>evil()</script>';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('ha evil()');
it('should escape unsafe HTML values', () => {
const template = `<div [innerHTML]="ctxProp">Text</div>`;
TestBed.overrideComponent(SecuredComponent, {set: {template}});
const fixture = TestBed.createComponent(SecuredComponent);
ci.ctxProp = 'also <img src="x" onerror="evil()"> evil';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('also <img src="x"> evil');
let e = fixture.debugElement.children[0].nativeElement;
let ci = fixture.debugElement.componentInstance;
// Make sure binding harmless values works.
ci.ctxProp = 'some <p>text</p>';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('some <p>text</p>');
ci.ctxProp = 'also <iframe srcdoc="evil"></iframe> evil';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('also evil');
ci.ctxProp = 'ha <script>evil()</script>';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('ha evil()');
async.done();
});
});
ci.ctxProp = 'also <img src="x" onerror="evil()"> evil';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('also <img src="x"> evil');
ci.ctxProp = 'also <iframe srcdoc="evil"></iframe> evil';
fixture.detectChanges();
expect(getDOM().getInnerHTML(e)).toEqual('also evil');
});
});
});
}