| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @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 {WrappedNodeExpr} from '@angular/compiler'; | 
					
						
							|  |  |  | import {TypeScriptAstFactory} from '@angular/compiler-cli/src/ngtsc/translator'; | 
					
						
							|  |  |  | import * as ts from 'typescript'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  | import {AstHost} from '../../src/ast/ast_host'; | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  | import {AstObject, AstValue} from '../../src/ast/ast_value'; | 
					
						
							|  |  |  | import {TypeScriptAstHost} from '../../src/ast/typescript/typescript_ast_host'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  | interface TestObject { | 
					
						
							|  |  |  |   a: number; | 
					
						
							|  |  |  |   b: string; | 
					
						
							|  |  |  |   c: boolean; | 
					
						
							|  |  |  |   d: {x: number; y: string}; | 
					
						
							|  |  |  |   e: number[]; | 
					
						
							|  |  |  |   missing: unknown; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const host: AstHost<ts.Expression> = new TypeScriptAstHost(); | 
					
						
							| 
									
										
										
										
											2021-02-26 11:55:19 -08:00
										 |  |  | const factory = new TypeScriptAstFactory(/* annotateForClosureCompiler */ false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  | const nestedObj = factory.createObjectLiteral([ | 
					
						
							|  |  |  |   {propertyName: 'x', quoted: false, value: factory.createLiteral(42)}, | 
					
						
							|  |  |  |   {propertyName: 'y', quoted: false, value: factory.createLiteral('X')}, | 
					
						
							|  |  |  | ]); | 
					
						
							|  |  |  | const nestedArray = | 
					
						
							|  |  |  |     factory.createArrayLiteral([factory.createLiteral(1), factory.createLiteral(2)]); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  | const obj = AstObject.parse<TestObject, ts.Expression>( | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     factory.createObjectLiteral([ | 
					
						
							|  |  |  |       {propertyName: 'a', quoted: false, value: factory.createLiteral(42)}, | 
					
						
							|  |  |  |       {propertyName: 'b', quoted: false, value: factory.createLiteral('X')}, | 
					
						
							|  |  |  |       {propertyName: 'c', quoted: false, value: factory.createLiteral(true)}, | 
					
						
							|  |  |  |       {propertyName: 'd', quoted: false, value: nestedObj}, | 
					
						
							|  |  |  |       {propertyName: 'e', quoted: false, value: nestedArray}, | 
					
						
							|  |  |  |     ]), | 
					
						
							|  |  |  |     host); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('AstObject', () => { | 
					
						
							|  |  |  |   describe('has()', () => { | 
					
						
							|  |  |  |     it('should return true if the property exists on the object', () => { | 
					
						
							|  |  |  |       expect(obj.has('a')).toBe(true); | 
					
						
							|  |  |  |       expect(obj.has('b')).toBe(true); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(obj.has('missing')).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(obj.has('x')).toBe(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getNumber()', () => { | 
					
						
							|  |  |  |     it('should return the number value of the property', () => { | 
					
						
							|  |  |  |       expect(obj.getNumber('a')).toEqual(42); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a number', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       expect(() => obj.getNumber('b')) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected a numeric literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getString()', () => { | 
					
						
							|  |  |  |     it('should return the string value of the property', () => { | 
					
						
							|  |  |  |       expect(obj.getString('b')).toEqual('X'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a string', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       expect(() => obj.getString('a')) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected a string literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getBoolean()', () => { | 
					
						
							|  |  |  |     it('should return the boolean value of the property', () => { | 
					
						
							|  |  |  |       expect(obj.getBoolean('c')).toEqual(true); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a boolean', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       expect(() => obj.getBoolean('b')) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected a boolean literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getObject()', () => { | 
					
						
							|  |  |  |     it('should return an AstObject instance parsed from the value of the property', () => { | 
					
						
							|  |  |  |       expect(obj.getObject('d')).toEqual(AstObject.parse(nestedObj, host)); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not an object expression', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       expect(() => obj.getObject('b')) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected an object literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getArray()', () => { | 
					
						
							|  |  |  |     it('should return an array of AstValue instances of parsed from the value of the property', | 
					
						
							|  |  |  |        () => { | 
					
						
							|  |  |  |          expect(obj.getArray('e')).toEqual([ | 
					
						
							|  |  |  |            new AstValue(factory.createLiteral(1), host), | 
					
						
							|  |  |  |            new AstValue(factory.createLiteral(2), host) | 
					
						
							|  |  |  |          ]); | 
					
						
							|  |  |  |        }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not an array of expressions', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       expect(() => obj.getArray('b')) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected an array literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getOpaque()', () => { | 
					
						
							|  |  |  |     it('should return the expression value of the property wrapped in a `WrappedNodeExpr`', () => { | 
					
						
							|  |  |  |       expect(obj.getOpaque('d')).toEqual(jasmine.any(WrappedNodeExpr)); | 
					
						
							|  |  |  |       expect(obj.getOpaque('d').node).toEqual(obj.getNode('d')); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property does not exist', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(() => obj.getOpaque('missing')) | 
					
						
							|  |  |  |           .toThrowError(`Expected property 'missing' to be present.`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => obj.getOpaque('x')).toThrowError(`Expected property 'x' to be present.`); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getNode()', () => { | 
					
						
							|  |  |  |     it('should return the original expression value of the property', () => { | 
					
						
							|  |  |  |       expect(obj.getNode('a')).toEqual(factory.createLiteral(42)); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property does not exist', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(() => obj.getNode('missing')) | 
					
						
							|  |  |  |           .toThrowError(`Expected property 'missing' to be present.`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => obj.getNode('x')).toThrowError(`Expected property 'x' to be present.`); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getValue()', () => { | 
					
						
							|  |  |  |     it('should return the expression value of the property wrapped in an `AstValue`', () => { | 
					
						
							|  |  |  |       expect(obj.getValue('a')).toEqual(jasmine.any(AstValue)); | 
					
						
							|  |  |  |       expect(obj.getValue('a').getNumber()).toEqual(42); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property does not exist', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(() => obj.getValue('missing')) | 
					
						
							|  |  |  |           .toThrowError(`Expected property 'missing' to be present.`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => obj.getValue('x')).toThrowError(`Expected property 'x' to be present.`); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('toLiteral()', () => { | 
					
						
							|  |  |  |     it('should convert the AstObject to a raw object with each property mapped', () => { | 
					
						
							|  |  |  |       expect(obj.toLiteral(value => value.getOpaque())).toEqual({ | 
					
						
							|  |  |  |         a: obj.getOpaque('a'), | 
					
						
							|  |  |  |         b: obj.getOpaque('b'), | 
					
						
							|  |  |  |         c: obj.getOpaque('c'), | 
					
						
							|  |  |  |         d: obj.getOpaque('d'), | 
					
						
							|  |  |  |         e: obj.getOpaque('e'), | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-10-30 22:53:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   describe('toMap()', () => { | 
					
						
							|  |  |  |     it('should convert the AstObject to a Map with each property mapped', () => { | 
					
						
							|  |  |  |       expect(obj.toMap(value => value.getOpaque())).toEqual(new Map([ | 
					
						
							|  |  |  |         ['a', obj.getOpaque('a')], | 
					
						
							|  |  |  |         ['b', obj.getOpaque('b')], | 
					
						
							|  |  |  |         ['c', obj.getOpaque('c')], | 
					
						
							|  |  |  |         ['d', obj.getOpaque('d')], | 
					
						
							|  |  |  |         ['e', obj.getOpaque('e')], | 
					
						
							|  |  |  |       ])); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |   function createAstValue<T>(node: ts.Expression): AstValue<T, ts.Expression> { | 
					
						
							|  |  |  |     return new AstValue<T, ts.Expression>(node, host); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 22:53:30 +01:00
										 |  |  |   describe('getSymbolName', () => { | 
					
						
							|  |  |  |     it('should return the name of an identifier', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createIdentifier('Foo')).getSymbolName()).toEqual('Foo'); | 
					
						
							| 
									
										
										
										
											2020-10-30 22:53:30 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return the name of a property access', () => { | 
					
						
							|  |  |  |       const propertyAccess = factory.createPropertyAccess( | 
					
						
							|  |  |  |           factory.createIdentifier('Foo'), factory.createIdentifier('Bar')); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(propertyAccess).getSymbolName()).toEqual('Bar'); | 
					
						
							| 
									
										
										
										
											2020-10-30 22:53:30 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return null if no symbol name is available', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral('a')).getSymbolName()).toBeNull(); | 
					
						
							| 
									
										
										
										
											2020-10-30 22:53:30 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |   describe('isNumber', () => { | 
					
						
							|  |  |  |     it('should return true if the value is a number', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isNumber()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not a number', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral('a')).isNumber()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getNumber', () => { | 
					
						
							|  |  |  |     it('should return the number value of the AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<number>(factory.createLiteral(42)).getNumber()).toEqual(42); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a number', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<string>(factory.createLiteral('a')).getNumber()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected a numeric literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('isString', () => { | 
					
						
							|  |  |  |     it('should return true if the value is a string', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral('a')).isString()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not a string', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isString()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getString', () => { | 
					
						
							|  |  |  |     it('should return the string value of the AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<string>(factory.createLiteral('X')).getString()).toEqual('X'); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a string', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getString()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected a string literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('isBoolean', () => { | 
					
						
							|  |  |  |     it('should return true if the value is a boolean', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(true)).isBoolean()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not a boolean', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isBoolean()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getBoolean', () => { | 
					
						
							|  |  |  |     it('should return the boolean value of the AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<boolean>(factory.createLiteral(true)).getBoolean()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a boolean', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getBoolean()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected a boolean literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('isObject', () => { | 
					
						
							|  |  |  |     it('should return true if the value is an object literal', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(nestedObj).isObject()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not an object literal', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isObject()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getObject', () => { | 
					
						
							|  |  |  |     it('should return the AstObject value of the AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<object>(nestedObj).getObject()) | 
					
						
							|  |  |  |           .toEqual(AstObject.parse(nestedObj, host)); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not an object literal', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getObject()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected an object literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('isArray', () => { | 
					
						
							|  |  |  |     it('should return true if the value is an array literal', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(nestedArray).isArray()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not an object literal', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isArray()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getArray', () => { | 
					
						
							|  |  |  |     it('should return an array of AstValue objects from the AstValue', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<number[]>(nestedArray).getArray()).toEqual([ | 
					
						
							|  |  |  |         createAstValue(factory.createLiteral(1)), | 
					
						
							|  |  |  |         createAstValue(factory.createLiteral(2)), | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not an array', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getArray()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected an array literal.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('isFunction', () => { | 
					
						
							|  |  |  |     it('should return true if the value is a function expression', () => { | 
					
						
							|  |  |  |       const funcExpr = factory.createFunctionExpression( | 
					
						
							|  |  |  |           'foo', [], | 
					
						
							|  |  |  |           factory.createBlock([factory.createReturnStatement(factory.createLiteral(42))])); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(funcExpr).isFunction()).toEqual(true); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value is not a function expression', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).isFunction()).toEqual(false); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getFunctionReturnValue', () => { | 
					
						
							|  |  |  |     it('should return the "return value" of the function expression', () => { | 
					
						
							|  |  |  |       const funcExpr = factory.createFunctionExpression( | 
					
						
							|  |  |  |           'foo', [], | 
					
						
							|  |  |  |           factory.createBlock([factory.createReturnStatement(factory.createLiteral(42))])); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue<Function>(funcExpr).getFunctionReturnValue()) | 
					
						
							|  |  |  |           .toEqual(createAstValue(factory.createLiteral(42))); | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is not a function expression', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       // @ts-expect-error
 | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getFunctionReturnValue()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toThrowError('Unsupported syntax, expected a function.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the property is a function expression with no return value', | 
					
						
							|  |  |  |        () => { | 
					
						
							|  |  |  |          const funcExpr = factory.createFunctionExpression( | 
					
						
							|  |  |  |              'foo', [], factory.createBlock([factory.createExpressionStatement( | 
					
						
							|  |  |  |                             factory.createLiteral('do nothing'))])); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |          expect(() => createAstValue<Function>(funcExpr).getFunctionReturnValue()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |              .toThrowError( | 
					
						
							|  |  |  |                  'Unsupported syntax, expected a function body with a single return statement.'); | 
					
						
							|  |  |  |        }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 22:35:35 +01:00
										 |  |  |   describe('isCallExpression', () => { | 
					
						
							|  |  |  |     it('should return true if the value represents a call expression', () => { | 
					
						
							|  |  |  |       const callExpr = factory.createCallExpression(factory.createIdentifier('foo'), [], false); | 
					
						
							|  |  |  |       expect(createAstValue<Function>(callExpr).isCallExpression()).toBe(true); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should return false if the value does not represent a call expression', () => { | 
					
						
							|  |  |  |       const fooExpr = factory.createIdentifier('foo'); | 
					
						
							|  |  |  |       expect(createAstValue<Function>(fooExpr).isCallExpression()).toBe(false); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getCallee', () => { | 
					
						
							|  |  |  |     it('should return the callee expression as a value', () => { | 
					
						
							|  |  |  |       const callExpr = factory.createCallExpression(factory.createIdentifier('foo'), [], false); | 
					
						
							|  |  |  |       expect(createAstValue<Function>(callExpr).getCallee()) | 
					
						
							|  |  |  |           .toEqual(createAstValue(factory.createIdentifier('foo'))); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the value is not a call expression', () => { | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getCallee()) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected a call expression.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getArguments', () => { | 
					
						
							|  |  |  |     it('should return the arguments as an array of values', () => { | 
					
						
							|  |  |  |       const callExpr = factory.createCallExpression( | 
					
						
							|  |  |  |           factory.createIdentifier('foo'), | 
					
						
							|  |  |  |           [ | 
					
						
							|  |  |  |             factory.createLiteral(1), | 
					
						
							|  |  |  |             factory.createLiteral(2), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |           false); | 
					
						
							|  |  |  |       expect(createAstValue<Function>(callExpr).getArguments()).toEqual([ | 
					
						
							|  |  |  |         createAstValue(factory.createLiteral(1)), | 
					
						
							|  |  |  |         createAstValue(factory.createLiteral(2)), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw an error if the value is not a call expression', () => { | 
					
						
							|  |  |  |       expect(() => createAstValue<number>(factory.createLiteral(42)).getArguments()) | 
					
						
							|  |  |  |           .toThrowError('Unsupported syntax, expected a call expression.'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |   describe('getOpaque()', () => { | 
					
						
							|  |  |  |     it('should return the value wrapped in a `WrappedNodeExpr`', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).getOpaque()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toEqual(jasmine.any(WrappedNodeExpr)); | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(factory.createLiteral(42)).getOpaque().node) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toEqual(factory.createLiteral(42)); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getRange()', () => { | 
					
						
							|  |  |  |     it('should return the source range of the AST node', () => { | 
					
						
							|  |  |  |       const file = ts.createSourceFile( | 
					
						
							|  |  |  |           'test.ts', '// preamble\nx = \'moo\';', ts.ScriptTarget.ES2015, | 
					
						
							|  |  |  |           /* setParentNodes */ true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Grab the `'moo'` string literal from the generated AST
 | 
					
						
							|  |  |  |       const stmt = file.statements[0] as ts.ExpressionStatement; | 
					
						
							|  |  |  |       const mooString = | 
					
						
							|  |  |  |           (stmt.expression as ts.AssignmentExpression<ts.Token<ts.SyntaxKind.EqualsToken>>).right; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check that this string literal has the expected range.
 | 
					
						
							| 
									
										
										
										
											2020-12-03 23:07:24 +01:00
										 |  |  |       expect(createAstValue(mooString).getRange()) | 
					
						
							| 
									
										
										
										
											2020-10-03 19:59:53 +01:00
										 |  |  |           .toEqual({startLine: 1, startCol: 4, startPos: 16, endPos: 21}); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |