diff --git a/packages/compiler-cli/test/ngtsc/template_mapping_spec.ts b/packages/compiler-cli/test/ngtsc/template_mapping_spec.ts
index c5711c4769..506f58f019 100644
--- a/packages/compiler-cli/test/ngtsc/template_mapping_spec.ts
+++ b/packages/compiler-cli/test/ngtsc/template_mapping_spec.ts
@@ -31,20 +31,22 @@ runInEachFileSystem((os) => {
describe('(element creation)', () => {
it('should map simple element with content', () => {
const mappings = compileAndMap('
Heading 1
');
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "h1")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'Heading 1',
generated: 'i0.ɵɵtext(1, "Heading 1")',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map void element', () => {
const mappings = compileAndMap('
');
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelement(0, "hr")', sourceUrl: '../test.ts'});
});
});
@@ -52,38 +54,40 @@ runInEachFileSystem((os) => {
describe('(interpolations)', () => {
it('should map a mix of interpolated and static content', () => {
const mappings = compileAndMap('Hello {{ name }}
');
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "h3")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'Hello {{ name }}',
generated: 'i0.ɵɵtextInterpolate1("Hello ", ctx.name, "")',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map a complex interpolated expression', () => {
const mappings = compileAndMap('{{ greeting + " " + name }}
');
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "h2")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '{{ greeting + " " + name }}',
generated: 'i0.ɵɵtextInterpolate(ctx.greeting + " " + ctx.name)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map interpolated properties', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelement(0, "div", 0)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'id="{{name}}"',
generated: 'i0.ɵɵpropertyInterpolate("id", ctx.name)',
sourceUrl: '../test.ts'
@@ -92,14 +96,16 @@ runInEachFileSystem((os) => {
it('should map interpolation with pipe', () => {
const mappings = compileAndMap('{{200.3 | percent : 2 }}
');
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "div")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '{{200.3 | percent : 2 }}',
generated: 'i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(2, 1, 200.3, 2))',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
});
@@ -107,12 +113,12 @@ runInEachFileSystem((os) => {
describe('(property bindings)', () => {
it('should map a simple input binding expression', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelement(0, "div", 0)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '[attr]="name"',
generated: 'i0.ɵɵproperty("attr", ctx.name)',
sourceUrl: '../test.ts'
@@ -122,12 +128,12 @@ runInEachFileSystem((os) => {
it('should map a complex input binding expression', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelement(0, "div", 0)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '[attr]="greeting + name"',
generated: 'i0.ɵɵproperty("attr", ctx.greeting + ctx.name)',
sourceUrl: '../test.ts'
@@ -136,12 +142,12 @@ runInEachFileSystem((os) => {
it('should map a longhand input binding expression', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelement(0, "div", 0)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'bind-attr="name"',
generated: 'i0.ɵɵproperty("attr", ctx.name)',
sourceUrl: '../test.ts'
@@ -150,72 +156,80 @@ runInEachFileSystem((os) => {
it('should map a simple output binding expression', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map a complex output binding expression', () => {
const mappings = compileAndMap(
``);
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: `', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map a longhand output binding expression', () => {
const mappings = compileAndMap('');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map a two-way binding expression', () => {
const mappings = compileAndMap('Name: ');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(1, "input", 0)',
sourceUrl: '../test.ts'
});
// TODO: improve mappings here
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '[(ngModel)]="name"',
generated:
'i0.ɵɵlistener("ngModelChange", function TestCmp_Template_input_ngModelChange_1_listener($event) { return ctx.name = $event; })',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementEnd()',
sourceUrl: '../test.ts'
@@ -224,19 +238,19 @@ runInEachFileSystem((os) => {
it('should map a longhand two-way binding expression', () => {
const mappings = compileAndMap('Name: ');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(1, "input", 0)',
sourceUrl: '../test.ts'
});
// TODO: improve mappings here
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'bindon-ngModel="name"',
generated:
'i0.ɵɵlistener("ngModelChange", function TestCmp_Template_input_ngModelChange_1_listener($event) { return ctx.name = $event; })',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementEnd()',
sourceUrl: '../test.ts'
@@ -245,7 +259,7 @@ runInEachFileSystem((os) => {
it('should map a class input binding', () => {
const mappings = compileAndMap('Message
');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts'
@@ -253,10 +267,12 @@ runInEachFileSystem((os) => {
// TODO: Add better mappings for binding
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: 'Message', generated: 'i0.ɵɵtext(1, "Message")', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
});
@@ -265,7 +281,7 @@ runInEachFileSystem((os) => {
it('should map *ngIf scenario', () => {
const mappings = compileAndMap('{{ name }}
');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts'
@@ -273,12 +289,13 @@ runInEachFileSystem((os) => {
// TODO - map the bindings better
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
// TODO: the `ctx_r...` appears to be dependent upon previous tests!!!
- // expect(mappings).toContain({
+ // expectMapping(mappings, {
// source: '{{ name }}',
// generated: 'i0.ɵɵtextInterpolate(ctx_r0.name)',
// sourceUrl: '../test.ts'
@@ -292,17 +309,19 @@ runInEachFileSystem((os) => {
`
\n` +
``);
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "div")', sourceUrl: '../test.ts'});
// TODO - map the bindings better
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
// TODO: the `ctx_r...` appears to be dependent upon previous tests!!!
- // expect(mappings).toContain({
+ // expectMapping(mappings, {
// source: '{{ name }}',
// generated: 'i0.ɵɵtextInterpolate(ctx_r0.name)',
// sourceUrl: '../test.ts'
@@ -313,7 +332,7 @@ runInEachFileSystem((os) => {
const mappings = compileAndMap(
'{{ item }}
');
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts'
@@ -321,7 +340,8 @@ runInEachFileSystem((os) => {
// TODO - map the bindings better
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
@@ -339,23 +359,26 @@ runInEachFileSystem((os) => {
`
\n` +
`
`);
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(0, "h3")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵprojection(1)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
+ expectMapping(
+ mappings, {source: '', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings,
{source: '', generated: 'i0.ɵɵelementStart(2, "div")', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵprojection(3, 1)',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{source: '
', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
});
@@ -363,12 +386,12 @@ runInEachFileSystem((os) => {
describe('$localize', () => {
it('should create simple i18n message source-mapping', () => {
const mappings = compileAndMap(`Hello, World!
`);
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'Hello, World!',
generated: '`Hello, World!`',
sourceUrl: '../test.ts',
@@ -377,27 +400,27 @@ runInEachFileSystem((os) => {
it('should create placeholder source-mappings', () => {
const mappings = compileAndMap(`
Hello, {{name}}!
`);
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '
',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '
',
generated: 'i0.ɵɵelementEnd()',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'Hello, ',
generated: '`Hello, ${',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '{{name}}',
generated: '"\\uFFFD0\\uFFFD"',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '!',
generated: '}:INTERPOLATION:!`',
sourceUrl: '../test.ts',
@@ -406,37 +429,37 @@ runInEachFileSystem((os) => {
it('should create tag (container) placeholder source-mappings', () => {
const mappings = compileAndMap(`
Hello, World!
`);
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '
',
generated: 'i0.ɵɵelementStart(0, "div")',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '
',
generated: 'i0.ɵɵelementEnd()',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'Hello, ',
generated: '`Hello, ${',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '
',
generated: '"\\uFFFD#2\\uFFFD"',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: 'World',
generated: '}:START_BOLD_TEXT:World${',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '',
generated: '"\\uFFFD/#2\\uFFFD"',
sourceUrl: '../test.ts',
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
source: '!',
generated: '}:CLOSE_BOLD_TEXT:!`',
sourceUrl: '../test.ts',
@@ -448,24 +471,26 @@ runInEachFileSystem((os) => {
const mappings = compileAndMap('
this is a test
{{ 1 + 2 }}
');
// Creation mode
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementStart(0, "div")', source: '
', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtext(1, "this is a test")',
source: 'this is a test',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementStart(2, "div")', source: '', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵelementEnd()', source: '', sourceUrl: '../test.ts'});
// Update mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtextInterpolate(1 + 2)',
source: '{{ 1 + 2 }}',
sourceUrl: '../test.ts'
@@ -476,25 +501,27 @@ runInEachFileSystem((os) => {
const mappings = compileAndMap('this is a test
{{ 1 + 2 }}
');
// Creation mode
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementStart(0, "div")', source: '', sourceUrl: '../test.ts'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtext(1, "this is a test")',
source: 'this is a test',
sourceUrl: '../test.ts'
});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵelementEnd()', source: '', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementStart(2, "div")', source: '', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../test.ts'});
- expect(mappings).toContain(
- {generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../test.ts'});
+ expectMapping(
+ mappings, {generated: 'i0.ɵɵelementEnd()', source: '', sourceUrl: '../test.ts'});
// TODO(benlesh): We need to circle back and prevent the extra parens from being generated.
// Update mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtextInterpolate(1 + 2)',
source: '{{ 1 + 2 }}',
sourceUrl: '../test.ts'
@@ -506,7 +533,7 @@ runInEachFileSystem((os) => {
// Note that the escaped double quotes, which need un-escaping to be parsed correctly.
const mappings = compileAndMap('this is a test
');
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementStart(0, "div", 0)',
source: '',
sourceUrl: '../test.ts'
@@ -525,30 +552,33 @@ runInEachFileSystem((os) => {
compileAndMap('
this is a test
{{ 1 + 2 }}
', './dir/test.html');
// Creation mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementStart(0, "div")',
source: '
',
sourceUrl: '../dir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtext(1, "this is a test")',
source: 'this is a test',
sourceUrl: '../dir/test.html'
});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../dir/test.html'});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementStart(2, "div")',
source: '
',
sourceUrl: '../dir/test.html'
});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../dir/test.html'});
- expect(mappings).toContain(
+ expectMapping(
+ mappings,
{generated: 'i0.ɵɵelementEnd()', source: '
', sourceUrl: '../dir/test.html'});
// Update mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtextInterpolate(1 + 2)',
source: '{{ 1 + 2 }}',
sourceUrl: '../dir/test.html'
@@ -560,39 +590,39 @@ runInEachFileSystem((os) => {
'
this is a test
{{ 1 + 2 }}
', 'extraRootDir/test.html');
// Creation mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementStart(0, "div")',
source: '
',
sourceUrl: '../extraRootDir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtext(1, "this is a test")',
source: 'this is a test',
sourceUrl: '../extraRootDir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementEnd()',
source: '
',
sourceUrl: '../extraRootDir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementStart(2, "div")',
source: '
',
sourceUrl: '../extraRootDir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtext(3)',
source: '{{ 1 + 2 }}',
sourceUrl: '../extraRootDir/test.html'
});
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵelementEnd()',
source: '
',
sourceUrl: '../extraRootDir/test.html'
});
// Update mode
- expect(mappings).toContain({
+ expectMapping(mappings, {
generated: 'i0.ɵɵtextInterpolate(1 + 2)',
source: '{{ 1 + 2 }}',
sourceUrl: '../extraRootDir/test.html'
@@ -638,5 +668,42 @@ runInEachFileSystem((os) => {
return value + padding;
}
}
+
+ function expectMapping(mappings: SegmentMapping[], expected: SegmentMapping): void {
+ if (mappings.some(
+ m => m.generated === expected.generated && m.source === expected.source &&
+ m.sourceUrl === expected.sourceUrl)) {
+ return;
+ }
+ const matchingGenerated = mappings.filter(m => m.generated === expected.generated);
+ const matchingSource = mappings.filter(m => m.source === expected.source);
+
+ const message = [
+ 'Expected mappings to contain the following mapping',
+ prettyPrintMapping(expected),
+ ];
+ if (matchingGenerated.length > 0) {
+ message.push('');
+ message.push('There are the following mappings that match the generated text:');
+ matchingGenerated.forEach(m => message.push(prettyPrintMapping(m)));
+ }
+ if (matchingSource.length > 0) {
+ message.push('');
+ message.push('There are the following mappings that match the source text:');
+ matchingSource.forEach(m => message.push(prettyPrintMapping(m)));
+ }
+
+ fail(message.join('\n'));
+ }
+
+ function prettyPrintMapping(mapping: SegmentMapping): string {
+ return [
+ '{',
+ ` generated: ${JSON.stringify(mapping.generated)}`,
+ ` source: ${JSON.stringify(mapping.source)}`,
+ ` sourceUrl: ${JSON.stringify(mapping.sourceUrl)}`,
+ '}',
+ ].join('\n');
+ }
});
});