/** * @license * Copyright Google LLC 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 {AbsoluteSourceSpan} from '@angular/compiler'; import {humanizeExpressionSource} from './util/expression'; import {parseR3 as parse} from './view/util'; describe('expression AST absolute source spans', () => { // TODO(ayazhafiz): duplicate this test without `preserveWhitespaces` once whitespace rewriting is // moved to post-R3AST generation. it('should provide absolute offsets with arbitrary whitespace', () => { expect(humanizeExpressionSource( parse('
\n \n{{foo}}
', {preserveWhitespaces: true}).nodes)) .toContain(['\n \n{{ foo }}', new AbsoluteSourceSpan(5, 16)]); }); it('should provide absolute offsets of an expression in a bound text', () => { expect(humanizeExpressionSource(parse('
{{foo}}
').nodes)).toContain([ '{{ foo }}', new AbsoluteSourceSpan(5, 12) ]); }); it('should provide absolute offsets of an expression in a bound event', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ 'foo(); bar();', new AbsoluteSourceSpan(14, 26) ]); expect(humanizeExpressionSource(parse('
').nodes)).toContain([ 'foo(); bar();', new AbsoluteSourceSpan(15, 27) ]); }); it('should provide absolute offsets of an expression in a bound attribute', () => { expect(humanizeExpressionSource(parse('').nodes)) .toContain(['condition ? true : false', new AbsoluteSourceSpan(19, 43)]); expect( humanizeExpressionSource(parse('').nodes)) .toContain(['condition ? true : false', new AbsoluteSourceSpan(22, 46)]); }); it('should provide absolute offsets of an expression in a template attribute', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ '(value | async)', new AbsoluteSourceSpan(12, 25) ]); }); describe('binary expression', () => { it('should provide absolute offsets of a binary expression', () => { expect(humanizeExpressionSource(parse('
{{1 + 2}}
').nodes)).toContain([ '1 + 2', new AbsoluteSourceSpan(7, 12) ]); }); it('should provide absolute offsets of expressions in a binary expression', () => { expect(humanizeExpressionSource(parse('
{{1 + 2}}
').nodes)) .toEqual(jasmine.arrayContaining([ ['1', new AbsoluteSourceSpan(7, 8)], ['2', new AbsoluteSourceSpan(11, 12)], ])); }); }); describe('conditional', () => { it('should provide absolute offsets of a conditional', () => { expect(humanizeExpressionSource(parse('
{{bool ? 1 : 0}}
').nodes)).toContain([ 'bool ? 1 : 0', new AbsoluteSourceSpan(7, 19) ]); }); it('should provide absolute offsets of expressions in a conditional', () => { expect(humanizeExpressionSource(parse('
{{bool ? 1 : 0}}
').nodes)) .toEqual(jasmine.arrayContaining([ ['bool', new AbsoluteSourceSpan(7, 11)], ['1', new AbsoluteSourceSpan(14, 15)], ['0', new AbsoluteSourceSpan(18, 19)], ])); }); }); describe('chain', () => { it('should provide absolute offsets of a chain', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ 'a(); b();', new AbsoluteSourceSpan(14, 23) ]); }); it('should provide absolute offsets of expressions in a chain', () => { expect(humanizeExpressionSource(parse('
').nodes)) .toEqual(jasmine.arrayContaining([ ['a()', new AbsoluteSourceSpan(14, 17)], ['b()', new AbsoluteSourceSpan(19, 22)], ])); }); }); describe('function call', () => { it('should provide absolute offsets of a function call', () => { expect(humanizeExpressionSource(parse('
{{fn()()}}
').nodes)).toContain([ 'fn()()', new AbsoluteSourceSpan(7, 13) ]); }); it('should provide absolute offsets of expressions in a function call', () => { expect(humanizeExpressionSource(parse('
{{fn()(param)}}
').nodes)).toContain([ 'param', new AbsoluteSourceSpan(12, 17) ]); }); }); it('should provide absolute offsets of an implicit receiver', () => { expect(humanizeExpressionSource(parse('
{{a.b}}
').nodes)).toContain([ '', new AbsoluteSourceSpan(7, 7) ]); }); describe('interpolation', () => { it('should provide absolute offsets of an interpolation', () => { expect(humanizeExpressionSource(parse('
{{1 + foo.length}}
').nodes)).toContain([ '{{ 1 + foo.length }}', new AbsoluteSourceSpan(5, 23) ]); }); it('should provide absolute offsets of expressions in an interpolation', () => { expect(humanizeExpressionSource(parse('
{{1 + 2}}
').nodes)) .toEqual(jasmine.arrayContaining([ ['1', new AbsoluteSourceSpan(7, 8)], ['2', new AbsoluteSourceSpan(11, 12)], ])); }); }); describe('keyed read', () => { it('should provide absolute offsets of a keyed read', () => { expect(humanizeExpressionSource(parse('
{{obj[key]}}
').nodes)).toContain([ 'obj[key]', new AbsoluteSourceSpan(7, 15) ]); }); it('should provide absolute offsets of expressions in a keyed read', () => { expect(humanizeExpressionSource(parse('
{{obj[key]}}
').nodes)).toContain([ 'key', new AbsoluteSourceSpan(11, 14) ]); }); }); describe('keyed write', () => { it('should provide absolute offsets of a keyed write', () => { expect(humanizeExpressionSource(parse('
{{obj[key] = 0}}
').nodes)).toContain([ 'obj[key] = 0', new AbsoluteSourceSpan(7, 19) ]); }); it('should provide absolute offsets of expressions in a keyed write', () => { expect(humanizeExpressionSource(parse('
{{obj[key] = 0}}
').nodes)) .toEqual(jasmine.arrayContaining([ ['key', new AbsoluteSourceSpan(11, 14)], ['0', new AbsoluteSourceSpan(18, 19)], ])); }); }); it('should provide absolute offsets of a literal primitive', () => { expect(humanizeExpressionSource(parse('
{{100}}
').nodes)).toContain([ '100', new AbsoluteSourceSpan(7, 10) ]); }); describe('literal array', () => { it('should provide absolute offsets of a literal array', () => { expect(humanizeExpressionSource(parse('
{{[0, 1, 2]}}
').nodes)).toContain([ '[0, 1, 2]', new AbsoluteSourceSpan(7, 16) ]); }); it('should provide absolute offsets of expressions in a literal array', () => { expect(humanizeExpressionSource(parse('
{{[0, 1, 2]}}
').nodes)) .toEqual(jasmine.arrayContaining([ ['0', new AbsoluteSourceSpan(8, 9)], ['1', new AbsoluteSourceSpan(11, 12)], ['2', new AbsoluteSourceSpan(14, 15)], ])); }); }); describe('literal map', () => { it('should provide absolute offsets of a literal map', () => { expect(humanizeExpressionSource(parse('
{{ {a: 0} }}
').nodes)).toContain([ '{a: 0}', new AbsoluteSourceSpan(8, 14) ]); }); it('should provide absolute offsets of expressions in a literal map', () => { expect(humanizeExpressionSource(parse('
{{ {a: 0} }}
').nodes)) .toEqual(jasmine.arrayContaining([ ['0', new AbsoluteSourceSpan(12, 13)], ])); }); }); describe('method call', () => { it('should provide absolute offsets of a method call', () => { expect(humanizeExpressionSource(parse('
{{method()}}
').nodes)).toContain([ 'method()', new AbsoluteSourceSpan(7, 15) ]); }); it('should provide absolute offsets of expressions in a method call', () => { expect(humanizeExpressionSource(parse('
{{method(param)}}
').nodes)).toContain([ 'param', new AbsoluteSourceSpan(14, 19) ]); }); }); describe('non-null assert', () => { it('should provide absolute offsets of a non-null assert', () => { expect(humanizeExpressionSource(parse('
{{prop!}}
').nodes)).toContain([ 'prop!', new AbsoluteSourceSpan(7, 12) ]); }); it('should provide absolute offsets of expressions in a non-null assert', () => { expect(humanizeExpressionSource(parse('
{{prop!}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(7, 11) ]); }); }); describe('pipe', () => { it('should provide absolute offsets of a pipe', () => { expect(humanizeExpressionSource(parse('
{{prop | pipe}}
').nodes)).toContain([ '(prop | pipe)', new AbsoluteSourceSpan(7, 18) ]); }); it('should provide absolute offsets expressions in a pipe', () => { expect(humanizeExpressionSource(parse('
{{prop | pipe}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(7, 11) ]); }); }); describe('property read', () => { it('should provide absolute offsets of a property read', () => { expect(humanizeExpressionSource(parse('
{{prop.obj}}
').nodes)).toContain([ 'prop.obj', new AbsoluteSourceSpan(7, 15) ]); }); it('should provide absolute offsets of expressions in a property read', () => { expect(humanizeExpressionSource(parse('
{{prop.obj}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(7, 11) ]); }); }); describe('property write', () => { it('should provide absolute offsets of a property write', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ 'prop = 0', new AbsoluteSourceSpan(14, 22) ]); }); it('should provide absolute offsets of an accessed property write', () => { expect(humanizeExpressionSource(parse('
').nodes)) .toContain(['prop.inner = 0', new AbsoluteSourceSpan(14, 28)]); }); it('should provide absolute offsets of expressions in a property write', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ '0', new AbsoluteSourceSpan(21, 22) ]); }); }); describe('"not" prefix', () => { it('should provide absolute offsets of a "not" prefix', () => { expect(humanizeExpressionSource(parse('
{{!prop}}
').nodes)).toContain([ '!prop', new AbsoluteSourceSpan(7, 12) ]); }); it('should provide absolute offsets of expressions in a "not" prefix', () => { expect(humanizeExpressionSource(parse('
{{!prop}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(8, 12) ]); }); }); describe('safe method call', () => { it('should provide absolute offsets of a safe method call', () => { expect(humanizeExpressionSource(parse('
{{prop?.safe()}}
').nodes)).toContain([ 'prop?.safe()', new AbsoluteSourceSpan(7, 19) ]); }); it('should provide absolute offsets of expressions in safe method call', () => { expect(humanizeExpressionSource(parse('
{{prop?.safe()}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(7, 11) ]); }); }); describe('safe property read', () => { it('should provide absolute offsets of a safe property read', () => { expect(humanizeExpressionSource(parse('
{{prop?.safe}}
').nodes)).toContain([ 'prop?.safe', new AbsoluteSourceSpan(7, 17) ]); }); it('should provide absolute offsets of expressions in safe property read', () => { expect(humanizeExpressionSource(parse('
{{prop?.safe}}
').nodes)).toContain([ 'prop', new AbsoluteSourceSpan(7, 11) ]); }); }); it('should provide absolute offsets of a quote', () => { expect(humanizeExpressionSource(parse('
').nodes)).toContain([ 'a:b', new AbsoluteSourceSpan(13, 16) ]); }); describe('absolute offsets for template expressions', () => { it('should work for simple cases', () => { expect( humanizeExpressionSource(parse('
{{item}}
').nodes)) .toContain(['items', new AbsoluteSourceSpan(25, 30)]); }); it('should work with multiple bindings', () => { expect(humanizeExpressionSource(parse('
').nodes)) .toEqual(jasmine.arrayContaining( [['As', new AbsoluteSourceSpan(22, 24)], ['Bs', new AbsoluteSourceSpan(35, 37)]])); }); }); });