test(ivy): move property and attribute tests to acceptance (#30321)
- splits existing property acceptance tests into property_binding and property_interpolation - ports tests from render3 instructions tests to acceptance tests - removes redundant or unnecessary tests that are covered by existing acceptance tests :) PR Close #30321
This commit is contained in:
parent
f26f036286
commit
b1d45ee6d2
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {By, DomSanitizer, SafeUrl} from '@angular/platform-browser';
|
||||
|
||||
describe('attribute creation', () => {
|
||||
it('should create an element', () => {
|
||||
@Component({
|
||||
template: `<div id="test" title="Hello"></div>`,
|
||||
})
|
||||
class Comp {
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
const div = fixture.debugElement.query(By.css('div')).nativeElement;
|
||||
expect(div.id).toEqual('test');
|
||||
expect(div.title).toEqual('Hello');
|
||||
});
|
||||
|
||||
it('should allow for setting xlink namespaced attributes', () => {
|
||||
@Component({
|
||||
template: `<div id="test" xlink:href="bar" title="Hello"></div>`,
|
||||
})
|
||||
class Comp {
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
|
||||
|
||||
const div = fixture.debugElement.query(By.css('div')).nativeElement;
|
||||
const attrs = div.attributes;
|
||||
|
||||
expect(attrs['id'].name).toEqual('id');
|
||||
expect(attrs['id'].namespaceURI).toEqual(null);
|
||||
expect(attrs['id'].value).toEqual('test');
|
||||
|
||||
expect(attrs['xlink:href'].name).toEqual('xlink:href');
|
||||
expect(attrs['xlink:href'].namespaceURI).toEqual('http://www.w3.org/1999/xlink');
|
||||
expect(attrs['xlink:href'].value).toEqual('bar');
|
||||
|
||||
expect(attrs['title'].name).toEqual('title');
|
||||
expect(attrs['title'].namespaceURI).toEqual(null);
|
||||
expect(attrs['title'].value).toEqual('Hello');
|
||||
});
|
||||
});
|
||||
|
||||
describe('attribute binding', () => {
|
||||
it('should set attribute values', () => {
|
||||
@Component({
|
||||
template: `<a [attr.href]="url"></a>`,
|
||||
})
|
||||
class Comp {
|
||||
url = 'https://angular.io/robots.txt';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const a = fixture.debugElement.query(By.css('a')).nativeElement;
|
||||
// NOTE: different browsers will add `//` into the URI.
|
||||
expect(a.href).toEqual('https://angular.io/robots.txt');
|
||||
});
|
||||
|
||||
it('should sanitize attribute values', () => {
|
||||
@Component({
|
||||
template: `<a [attr.href]="badUrl"></a>`,
|
||||
})
|
||||
class Comp {
|
||||
badUrl: string|SafeUrl = 'javascript:true';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const a = fixture.debugElement.query(By.css('a')).nativeElement;
|
||||
// NOTE: different browsers will add `//` into the URI.
|
||||
expect(a.href.indexOf('unsafe:')).toBe(0);
|
||||
|
||||
const domSanitizer: DomSanitizer = TestBed.get(DomSanitizer);
|
||||
fixture.componentInstance.badUrl =
|
||||
domSanitizer.bypassSecurityTrustUrl('javascript:alert("this is fine")');
|
||||
fixture.detectChanges();
|
||||
|
||||
// should not start with `unsafe:`.
|
||||
expect(a.href.indexOf('unsafe:')).toBe(-1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {By, DomSanitizer, SafeUrl} from '@angular/platform-browser';
|
||||
|
||||
describe('property bindings', () => {
|
||||
it('should update bindings when value changes', () => {
|
||||
@Component({
|
||||
template: `<a [title]="title"></a>`,
|
||||
})
|
||||
class Comp {
|
||||
title = 'Hello';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
let a = fixture.debugElement.query(By.css('a')).nativeElement;
|
||||
expect(a.title).toBe('Hello');
|
||||
|
||||
fixture.componentInstance.title = 'World';
|
||||
fixture.detectChanges();
|
||||
expect(a.title).toBe('World');
|
||||
});
|
||||
|
||||
it('should not update bindings when value does not change', () => {
|
||||
@Component({
|
||||
template: `<a [title]="title"></a>`,
|
||||
})
|
||||
class Comp {
|
||||
title = 'Hello';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
let a = fixture.debugElement.query(By.css('a')).nativeElement;
|
||||
expect(a.title).toBe('Hello');
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(a.title).toBe('Hello');
|
||||
});
|
||||
|
||||
it('should bind to properties whose names do not correspond to their attribute names', () => {
|
||||
@Component({template: '<label [for]="forValue"></label>'})
|
||||
class MyComp {
|
||||
forValue?: string;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [MyComp]});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
const labelNode = fixture.debugElement.query(By.css('label'));
|
||||
|
||||
fixture.componentInstance.forValue = 'some-input';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(labelNode.nativeElement.getAttribute('for')).toBe('some-input');
|
||||
|
||||
fixture.componentInstance.forValue = 'some-textarea';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(labelNode.nativeElement.getAttribute('for')).toBe('some-textarea');
|
||||
});
|
||||
|
||||
it('should not map properties whose names do not correspond to their attribute names, ' +
|
||||
'if they correspond to inputs',
|
||||
() => {
|
||||
|
||||
@Component({template: '', selector: 'my-comp'})
|
||||
class MyComp {
|
||||
@Input() for !:string;
|
||||
}
|
||||
|
||||
@Component({template: '<my-comp [for]="forValue"></my-comp>'})
|
||||
class App {
|
||||
forValue?: string;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App, MyComp]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const myCompNode = fixture.debugElement.query(By.directive(MyComp));
|
||||
fixture.componentInstance.forValue = 'hello';
|
||||
fixture.detectChanges();
|
||||
expect(myCompNode.nativeElement.getAttribute('for')).toBeFalsy();
|
||||
expect(myCompNode.componentInstance.for).toBe('hello');
|
||||
|
||||
fixture.componentInstance.forValue = 'hej';
|
||||
fixture.detectChanges();
|
||||
expect(myCompNode.nativeElement.getAttribute('for')).toBeFalsy();
|
||||
expect(myCompNode.componentInstance.for).toBe('hej');
|
||||
});
|
||||
|
||||
it('should use the sanitizer in bound properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<a [href]="url">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
url: string|SafeUrl = 'javascript:alert("haha, I am taking over your computer!!!");';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const a = fixture.nativeElement.querySelector('a');
|
||||
|
||||
expect(a.href.indexOf('unsafe:')).toBe(0);
|
||||
|
||||
const domSanitzer: DomSanitizer = TestBed.get(DomSanitizer);
|
||||
fixture.componentInstance.url =
|
||||
domSanitzer.bypassSecurityTrustUrl('javascript:alert("the developer wanted this");');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(a.href.indexOf('unsafe:')).toBe(-1);
|
||||
});
|
||||
|
||||
it('should not stringify non-string values', () => {
|
||||
@Component({
|
||||
template: `<input [required]="isRequired"/>`,
|
||||
})
|
||||
class Comp {
|
||||
isRequired = false;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [Comp]});
|
||||
const fixture = TestBed.createComponent(Comp);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.debugElement.query(By.css('input')).nativeElement.required).toBe(false);
|
||||
});
|
||||
});
|
|
@ -5,82 +5,12 @@
|
|||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {of } from 'rxjs';
|
||||
|
||||
describe('property instructions', () => {
|
||||
it('should bind to properties whose names do not correspond to their attribute names', () => {
|
||||
@Component({template: '<label [for]="forValue"></label>'})
|
||||
class MyComp {
|
||||
forValue?: string;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [MyComp]});
|
||||
const fixture = TestBed.createComponent(MyComp);
|
||||
const labelNode = fixture.debugElement.query(By.css('label'));
|
||||
|
||||
fixture.componentInstance.forValue = 'some-input';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(labelNode.nativeElement.getAttribute('for')).toBe('some-input');
|
||||
|
||||
fixture.componentInstance.forValue = 'some-textarea';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(labelNode.nativeElement.getAttribute('for')).toBe('some-textarea');
|
||||
});
|
||||
|
||||
it('should not allow unsanitary urls in bound properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<img [src]="naughty">
|
||||
`
|
||||
})
|
||||
class App {
|
||||
naughty = 'javascript:alert("haha, I am taking over your computer!!!");';
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
fixture.detectChanges();
|
||||
const img = fixture.nativeElement.querySelector('img');
|
||||
|
||||
expect(img.src.indexOf('unsafe:')).toBe(0);
|
||||
});
|
||||
|
||||
|
||||
it('should not map properties whose names do not correspond to their attribute names, ' +
|
||||
'if they correspond to inputs',
|
||||
() => {
|
||||
|
||||
@Component({template: '', selector: 'my-comp'})
|
||||
class MyComp {
|
||||
@Input() for !:string;
|
||||
}
|
||||
|
||||
@Component({template: '<my-comp [for]="forValue"></my-comp>'})
|
||||
class App {
|
||||
forValue?: string;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [App, MyComp]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const myCompNode = fixture.debugElement.query(By.directive(MyComp));
|
||||
fixture.componentInstance.forValue = 'hello';
|
||||
fixture.detectChanges();
|
||||
expect(myCompNode.nativeElement.getAttribute('for')).toBeFalsy();
|
||||
expect(myCompNode.componentInstance.for).toBe('hello');
|
||||
|
||||
fixture.componentInstance.forValue = 'hej';
|
||||
fixture.detectChanges();
|
||||
expect(myCompNode.nativeElement.getAttribute('for')).toBeFalsy();
|
||||
expect(myCompNode.componentInstance.for).toBe('hej');
|
||||
});
|
||||
|
||||
describe('property interpolation', () => {
|
||||
it('should handle all flavors of interpolated properties', () => {
|
||||
@Component({
|
||||
template: `
|
||||
|
@ -230,4 +160,70 @@ describe('property instructions', () => {
|
|||
.toEqual(
|
||||
`http://g.com/?one=1&two=2&three=3&four=4&five=5&six=6&seven=7&eight=8&nine=9&ten=10`);
|
||||
});
|
||||
|
||||
it('should support the chained use cases of propertyInterpolate instructions', () => {
|
||||
// The below *just happens* to have two attributes in a row that have the same interpolation
|
||||
// count.
|
||||
@Component({
|
||||
template: `
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i{{nine}}j" alt="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i{{nine}}j"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i" alt="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h" alt="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g" alt="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f" alt="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d{{four}}e" alt="a{{one}}b{{two}}c{{three}}d{{four}}e"/>
|
||||
<img title="a{{one}}b{{two}}c{{three}}d" alt="a{{one}}b{{two}}c{{three}}d"/>
|
||||
<img title="a{{one}}b{{two}}c" alt="a{{one}}b{{two}}c"/>
|
||||
<img title="a{{one}}b" alt="a{{one}}b"/>
|
||||
<img title="{{one}}" alt="{{one}}"/>
|
||||
`
|
||||
})
|
||||
class AppComp {
|
||||
one = 1;
|
||||
two = 2;
|
||||
three = 3;
|
||||
four = 4;
|
||||
five = 5;
|
||||
six = 6;
|
||||
seven = 7;
|
||||
eight = 8;
|
||||
nine = 9;
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [AppComp]});
|
||||
const fixture = TestBed.createComponent(AppComp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const titles = Array.from(fixture.nativeElement.querySelectorAll('img[title]'))
|
||||
.map((img: HTMLImageElement) => img.title);
|
||||
|
||||
expect(titles).toEqual([
|
||||
'a1b2c3d4e5f6g7h8i9j',
|
||||
'a1b2c3d4e5f6g7h8i',
|
||||
'a1b2c3d4e5f6g7h',
|
||||
'a1b2c3d4e5f6g',
|
||||
'a1b2c3d4e5f',
|
||||
'a1b2c3d4e',
|
||||
'a1b2c3d',
|
||||
'a1b2c',
|
||||
'a1b',
|
||||
'1',
|
||||
]);
|
||||
|
||||
const others = Array.from(fixture.nativeElement.querySelectorAll('img[alt]'))
|
||||
.map((img: HTMLImageElement) => img.alt);
|
||||
|
||||
expect(others).toEqual([
|
||||
'a1b2c3d4e5f6g7h8i9j',
|
||||
'a1b2c3d4e5f6g7h8i',
|
||||
'a1b2c3d4e5f6g7h',
|
||||
'a1b2c3d4e5f6g',
|
||||
'a1b2c3d4e5f',
|
||||
'a1b2c3d4e',
|
||||
'a1b2c3d',
|
||||
'a1b2c',
|
||||
'a1b',
|
||||
'1',
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import {NgForOfContext} from '@angular/common';
|
||||
import {ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV} from '@angular/core/src/render3/instructions/all';
|
||||
|
||||
import {ɵɵdefineComponent} from '../../src/render3/definition';
|
||||
import {RenderFlags, ɵɵbind, ɵɵclassMap, ɵɵelement, ɵɵelementAttribute, ɵɵelementEnd, ɵɵelementProperty, ɵɵelementStart, ɵɵinterpolation1, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/index';
|
||||
|
@ -45,8 +44,18 @@ describe('instructions', () => {
|
|||
|
||||
function createScript() { ɵɵelement(0, 'script'); }
|
||||
|
||||
describe('ɵɵselect', () => {
|
||||
it('should error in DevMode if index is out of range', () => {
|
||||
// Only one constant added, meaning only index `0` is valid.
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 0);
|
||||
expect(() => { t.update(() => { ɵɵselect(-1); }); }).toThrow();
|
||||
expect(() => { t.update(() => { ɵɵselect(1); }); }).toThrow();
|
||||
expect(() => { t.update(() => { ɵɵselect(0); }); }).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('bind', () => {
|
||||
it('should update bindings when value changes', () => {
|
||||
it('should update bindings when value changes with the correct perf counters', () => {
|
||||
const t = new TemplateFixture(createAnchor, () => {}, 1, 1);
|
||||
|
||||
t.update(() => ɵɵelementProperty(0, 'title', ɵɵbind('Hello')));
|
||||
|
@ -63,27 +72,28 @@ describe('instructions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should not update bindings when value does not change', () => {
|
||||
const idempotentUpdate = () => ɵɵelementProperty(0, 'title', ɵɵbind('Hello'));
|
||||
const t = new TemplateFixture(createAnchor, idempotentUpdate, 1, 1);
|
||||
it('should not update bindings when value does not change, with the correct perf counters',
|
||||
() => {
|
||||
const idempotentUpdate = () => ɵɵelementProperty(0, 'title', ɵɵbind('Hello'));
|
||||
const t = new TemplateFixture(createAnchor, idempotentUpdate, 1, 1);
|
||||
|
||||
t.update();
|
||||
expect(t.html).toEqual('<a title="Hello"></a>');
|
||||
t.update();
|
||||
expect(t.html).toEqual('<a title="Hello"></a>');
|
||||
|
||||
t.update();
|
||||
expect(t.html).toEqual('<a title="Hello"></a>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for hostElement + 1 for the template under test
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 1
|
||||
});
|
||||
});
|
||||
t.update();
|
||||
expect(t.html).toEqual('<a title="Hello"></a>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for hostElement + 1 for the template under test
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 1
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('element', () => {
|
||||
it('should create an element', () => {
|
||||
it('should create an element with the correct perf counters', () => {
|
||||
const t = new TemplateFixture(() => {
|
||||
ɵɵelement(0, 'div', ['id', 'test', 'title', 'Hello']);
|
||||
}, () => {}, 1);
|
||||
|
@ -98,47 +108,6 @@ describe('instructions', () => {
|
|||
rendererCreateElement: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow setting namespaced attributes', () => {
|
||||
const t = new TemplateFixture(() => {
|
||||
ɵɵelement(0, 'div', [
|
||||
// id="test"
|
||||
'id',
|
||||
'test',
|
||||
// test:foo="bar"
|
||||
AttributeMarker.NamespaceURI,
|
||||
'http://someuri.com/2018/test',
|
||||
'test:foo',
|
||||
'bar',
|
||||
// title="Hello"
|
||||
'title',
|
||||
'Hello',
|
||||
]);
|
||||
}, () => {}, 1);
|
||||
|
||||
const div = (t.hostElement as HTMLElement).querySelector('div') !;
|
||||
const attrs: any = div.attributes;
|
||||
|
||||
expect(attrs['id'].name).toEqual('id');
|
||||
expect(attrs['id'].namespaceURI).toEqual(null);
|
||||
expect(attrs['id'].value).toEqual('test');
|
||||
|
||||
expect(attrs['test:foo'].name).toEqual('test:foo');
|
||||
expect(attrs['test:foo'].namespaceURI).toEqual('http://someuri.com/2018/test');
|
||||
expect(attrs['test:foo'].value).toEqual('bar');
|
||||
|
||||
expect(attrs['title'].name).toEqual('title');
|
||||
expect(attrs['title'].namespaceURI).toEqual(null);
|
||||
expect(attrs['title'].value).toEqual('Hello');
|
||||
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetAttribute: 3
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('elementAttribute', () => {
|
||||
|
@ -162,41 +131,12 @@ describe('instructions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('ɵɵselect', () => {
|
||||
it('should error in DevMode if index is out of range', () => {
|
||||
// Only one constant added, meaning only index `0` is valid.
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 0);
|
||||
expect(() => { t.update(() => { ɵɵselect(-1); }); }).toThrow();
|
||||
expect(() => { t.update(() => { ɵɵselect(1); }); }).toThrow();
|
||||
expect(() => { t.update(() => { ɵɵselect(0); }); }).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('property', () => {
|
||||
// TODO(benlesh): Replace with TestBed tests once the instruction is being generated.
|
||||
it('should set properties of the ɵɵselected element', () => {
|
||||
// <div [title]="title"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵproperty('title', 'one');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="one"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵproperty('title', 'two');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="two"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
// TODO(benlesh): Replace with TestBed tests once the instruction is being generated.
|
||||
/**
|
||||
* TODO: We need to replace this with an acceptance test, but for right now,
|
||||
* this is the only test that ensures chaining works, since code generation
|
||||
* is not producing chained instructions yet.
|
||||
*/
|
||||
it('should chain', () => {
|
||||
// <div [title]="title" [accesskey]="key"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
|
@ -219,29 +159,6 @@ describe('instructions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO(benlesh): Replace with TestBed tests once the instruction is being generated.
|
||||
it('should diff value changes', () => {
|
||||
// <div [title]="title" [accesskey]="key"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵproperty('title', 'one')('accessKey', 'A');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="A" title="one"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵproperty('title', 'two')('accessKey', 'A'); // Notice: only changing the title.
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="A" title="two"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 3,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error in dev mode if ɵɵselect was not called prior', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
expect(() => { t.update(() => { ɵɵproperty('title', 'test'); }); }).toThrow();
|
||||
|
@ -254,762 +171,6 @@ describe('instructions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* TODO: REMOVE ALL OF THESE TemplateFixture TESTS FOR TestBed TESTS AFTER COMPILER IS UPDATED
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
*/
|
||||
describe('ɵɵpropertyInterpolate instructions', () => {
|
||||
describe('ɵɵpropertyInterpolate', () => {
|
||||
it('should interpolate one value', () => {
|
||||
// <div title="{{123}}"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate('title', 123);
|
||||
});
|
||||
expect(t.html).toEqual('<div title="123"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate('title', 'abc');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="abc"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="{{123}}" accesskey="{{'A'}}"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate('title', 123)('accessKey', 'A');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="A" title="123"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate('title', 'abc')('accessKey', 'B');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="B" title="abc"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
expect(() => { t.update(() => { ɵɵpropertyInterpolate('title', 123); }); }).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => { ɵɵpropertyInterpolate('title', 123); });
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate1', () => {
|
||||
it('should interpolate one value', () => {
|
||||
// <div title="start{{123}}end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate1('title', 'start', 123, 'end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start123end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate1('title', 'start', 'abc', 'end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="startabcend"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start{{123}}end" data-teststartstart{{'A'}}end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate1('title', 'start', 123, 'end')('accessKey', 'start', 'A', 'end');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="startAend" title="start123end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate1('title', 'start', 'abc', 'end')('accessKey', 'start', 'B', 'end');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="startBend" title="startabcend"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 1);
|
||||
expect(() => {
|
||||
t.update(() => { ɵɵpropertyInterpolate1('title', 'start', 'whatever', 'end'); });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => { ɵɵpropertyInterpolate1('title', 'start', 'whatever', 'end'); });
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate2', () => {
|
||||
it('should interpolate two values', () => {
|
||||
// <div title="start: {{v0}}, 1: {{v1}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate2('title', 'start: ', 0, ', 1: ', 1, ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: 0, 1: 1, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate2('title', 'start: ', 'A', ', 1: ', 'B', ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: A, 1: B, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}}, end" accesskey="start: {{v0}}, 1: {{v1}},
|
||||
// end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 4);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate2('title', 'start: ', 0, ', 1: ', 1, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, end" title="start: 0, 1: 1, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate2('title', 'start: ', 'A', ', 1: ', 'B', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, end" title="start: A, 1: B, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 2);
|
||||
expect(() => {
|
||||
t.update(() => { ɵɵpropertyInterpolate2('title', '', '', '', '', ''); });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => { ɵɵpropertyInterpolate2('title', '', '', '', '', ''); });
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate3', () => {
|
||||
it('should interpolate three values', () => {
|
||||
// <div title="start: {{v0}}, 1: {{v1}}, 2: {{v2}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 3);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate3('title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: 0, 1: 1, 2: 2, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate3('title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: A, 1: B, 2: C, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}}, end" accesskey="start: {{v0}}, 1: {{v1}},
|
||||
// 2: {{v2}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 6);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate3('title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, end" title="start: 0, 1: 1, 2: 2, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate3('title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, end" title="start: A, 1: B, 2: C, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 3);
|
||||
expect(() => {
|
||||
t.update(() => { ɵɵpropertyInterpolate3('title', '', '', '', '', '', '', ''); });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => { ɵɵpropertyInterpolate3('title', '', '', '', '', '', '', ''); });
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('ɵɵpropertyInterpolate4', () => {
|
||||
it('should interpolate four values', () => {
|
||||
// <div title="start: {{v0}}, 1: {{v1}}, 2: {{v2}}, 3: {{v3}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 4);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate4(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: 0, 1: 1, 2: 2, 3: 3, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate4(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: A, 1: B, 2: C, 3: D, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}}, end" accesskey="start: {{v0}} 1:
|
||||
// {{v1}} 2: {{v2}} 3: {{v3}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 8);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate4(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, end" title="start: 0, 1: 1, 2: 2, 3: 3, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate4(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, end" title="start: A, 1: B, 2: C, 3: D, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 4);
|
||||
expect(() => {
|
||||
t.update(() => { ɵɵpropertyInterpolate4('title', '', '', '', '', '', '', '', '', ''); });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => { ɵɵpropertyInterpolate4('title', '', '', '', '', '', '', '', '', ''); });
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate5', () => {
|
||||
it('should interpolate five values', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 5);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate5(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate5(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: A, 1: B, 2: C, 3: D, 4: E, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, end" accesskey="start:
|
||||
// {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 10);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate5(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, end" title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate5(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, 4: E, end" title="start: A, 1: B, 2: C, 3: D, 4: E, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 5);
|
||||
expect(() => {
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate5('title', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate5('title', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate6', () => {
|
||||
it('should interpolate six values', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, 5: {{v5}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 6);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate6(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate6(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', end');
|
||||
});
|
||||
expect(t.html).toEqual('<div title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, 5: {{v5}}, end"
|
||||
// accesskey="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}}, 5: {{v5}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 12);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate6(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, end" title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate6(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, end" title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 6);
|
||||
expect(() => {
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate6('title', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate6('title', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate7', () => {
|
||||
it('should interpolate seven values', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 7);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// 7: {{v7}} end" accesskey="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5:
|
||||
// {{v5}}, 6: {{v6}}, end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 14);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, end" title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, end" title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 7);
|
||||
expect(() => {
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate7(
|
||||
'title', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ɵɵpropertyInterpolate8', () => {
|
||||
it('should interpolate eight values', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// 7: {{v7}} end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 8);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', 7: ', 7, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', 7: ', 'H', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// 7: {{v7}} end" accesskey="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5:
|
||||
// {{v5}}, 6: {{v6}}, 7: {{v7}} end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 16);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', 7: ', 7, ', end')(
|
||||
'accessKey', 'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5,
|
||||
', 6: ', 6, ', 7: ', 7, ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, end" title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', 7: ', 'H', ', end')(
|
||||
'accessKey', 'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E',
|
||||
', 5: ', 'F', ', 6: ', 'G', ', 7: ', 'H', ', end');
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, end" title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 8);
|
||||
expect(() => {
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolate8(
|
||||
'title', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('ɵɵpropertyInterpolateV', () => {
|
||||
it('should interpolate eight or more values', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// 7: {{v7}}, 8: {{v8}} end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 9);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolateV('title', [
|
||||
'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5, ', 6: ', 6,
|
||||
', 7: ', 7, ', 8: ', 8, ', end'
|
||||
]);
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolateV('title', [
|
||||
'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E', ', 5: ', 'F',
|
||||
', 6: ', 'G', ', 7: ', 'H', ', 8: ', 'I', ', end'
|
||||
]);
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should chain', () => {
|
||||
// <div title="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5: {{v5}}, 6: {{v6}},
|
||||
// 7: {{v7}} end" accesskey="start: {{v0}} 1: {{v1}} 2: {{v2}} 3: {{v3}} 4: {{v4}} 5:
|
||||
// {{v5}}, 6: {{v6}}, 7: {{v7}}, 8: {{v8}} end"></div>
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 18);
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolateV(
|
||||
'title',
|
||||
[
|
||||
'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5, ', 6: ',
|
||||
6, ', 7: ', 7, ', 8: ', 8, ', end'
|
||||
])(
|
||||
'accessKey', [
|
||||
'start: ', 0, ', 1: ', 1, ', 2: ', 2, ', 3: ', 3, ', 4: ', 4, ', 5: ', 5, ', 6: ',
|
||||
6, ', 7: ', 7, ', 8: ', 8, ', end'
|
||||
]);
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, end" title="start: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, end"></div>');
|
||||
t.update(() => {
|
||||
ɵɵselect(0);
|
||||
ɵɵpropertyInterpolateV(
|
||||
'title',
|
||||
[
|
||||
'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E', ', 5: ',
|
||||
'F', ', 6: ', 'G', ', 7: ', 'H', ', 8: ', 'I', ', end'
|
||||
])(
|
||||
'accessKey', [
|
||||
'start: ', 'A', ', 1: ', 'B', ', 2: ', 'C', ', 3: ', 'D', ', 4: ', 'E', ', 5: ',
|
||||
'F', ', 6: ', 'G', ', 7: ', 'H', ', 8: ', 'I', ', end'
|
||||
]);
|
||||
});
|
||||
expect(t.html).toEqual(
|
||||
'<div accesskey="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, end" title="start: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, end"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if called without ɵɵselect called first', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1, 9);
|
||||
expect(() => {
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolateV(
|
||||
'title',
|
||||
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
|
||||
});
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
ɵɵselect(0);
|
||||
t.update(() => {
|
||||
ɵɵpropertyInterpolateV(
|
||||
'title',
|
||||
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']);
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('elementProperty', () => {
|
||||
it('should use sanitizer function when available', () => {
|
||||
const t = new TemplateFixture(createDiv, () => {}, 1);
|
||||
|
||||
t.update(() => ɵɵelementProperty(0, 'title', 'javascript:true', ɵɵsanitizeUrl));
|
||||
expect(t.html).toEqual('<div title="unsafe:javascript:true"></div>');
|
||||
|
||||
t.update(
|
||||
() => ɵɵelementProperty(
|
||||
0, 'title', bypassSanitizationTrustUrl('javascript:false'), ɵɵsanitizeUrl));
|
||||
expect(t.html).toEqual('<div title="javascript:false"></div>');
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not stringify non string values', () => {
|
||||
const t = new TemplateFixture(() => { ɵɵelement(0, 'input'); }, () => {}, 1);
|
||||
|
||||
// Note: don't use 'hidden' here because IE10 does not support the hidden property
|
||||
t.update(() => ɵɵelementProperty(0, 'required', false));
|
||||
// The required property would be true if `false` was stringified into `"false"`.
|
||||
expect((t.hostElement as HTMLElement).querySelector('input') !.required).toEqual(false);
|
||||
expect(ngDevMode).toHaveProperties({
|
||||
firstTemplatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 1
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('styleProp', () => {
|
||||
it('should automatically sanitize unless a bypass operation is applied', () => {
|
||||
const t = new TemplateFixture(() => {
|
||||
|
|
Loading…
Reference in New Issue