| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 20:43:20 -08:00
										 |  |  | import {Attribute, ChangeDetectorRef, ElementRef, Host, INJECTOR, Inject, InjectFlags, Injector, Optional, Renderer2, Self, SkipSelf, TemplateRef, ViewContainerRef, defineInjectable, defineInjector} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  | import {ComponentType, RenderFlags} from '@angular/core/src/render3/interfaces/definition'; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {createInjector} from '../../src/di/r3_injector'; | 
					
						
							| 
									
										
										
										
											2018-01-17 10:09:05 -08:00
										 |  |  | import {defineComponent} from '../../src/render3/definition'; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  | import {bloomAdd, bloomHasToken, bloomHashBitOrFactory as bloomHash, getOrCreateNodeInjectorForNode} from '../../src/render3/di'; | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {ProvidersFeature, defineDirective, elementProperty, load, templateRefExtractor, elementStart, text, elementEnd, reference, textBinding, bind, directiveInject, element, container, containerRefreshStart, embeddedViewStart, embeddedViewEnd, containerRefreshEnd, template, allocHostVars, interpolation2, elementContainerStart, elementContainerEnd, projectionDef, projection, injectAttribute} from '../../src/render3/index'; | 
					
						
							|  |  |  | import {LContainer, NATIVE} from '../../src/render3/interfaces/container'; | 
					
						
							|  |  |  | import {TNODE} from '../../src/render3/interfaces/injector'; | 
					
						
							| 
									
										
										
										
											2018-10-12 18:49:00 -07:00
										 |  |  | import {AttributeMarker, TNodeType} from '../../src/render3/interfaces/node'; | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {RElement, isProceduralRenderer} from '../../src/render3/interfaces/renderer'; | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  | import {LViewFlags} from '../../src/render3/interfaces/view'; | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {enterView, getLView, leaveView} from '../../src/render3/state'; | 
					
						
							|  |  |  | import {getNativeByIndex} from '../../src/render3/util/view_utils'; | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | import {ViewRef} from '../../src/render3/view_ref'; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {NgIf} from './common_with_def'; | 
					
						
							| 
									
										
										
										
											2018-08-16 17:43:29 +02:00
										 |  |  | import {getRendererFactory2} from './imported_renderer2'; | 
					
						
							| 
									
										
										
										
											2018-10-05 21:23:41 -07:00
										 |  |  | import {ComponentFixture, createComponent, createDirective, getDirectiveOnNode, renderComponent, toHtml} from './render_util'; | 
					
						
							| 
									
										
										
										
											2019-04-01 15:36:43 -07:00
										 |  |  | import {createLView, createTView, createNodeAtIndex} from '@angular/core/src/render3/instructions/shared'; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('di', () => { | 
					
						
							|  |  |  |   describe('no dependencies', () => { | 
					
						
							|  |  |  |     it('should create directive with no deps', () => { | 
					
						
							|  |  |  |       class Directive { | 
					
						
							|  |  |  |         value: string = 'Created'; | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: Directive, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'dir', '']], | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |           factory: () => new Directive, | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |       /** <div dir #dir="dir"> {{ dir.value }}  </div> */ | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |           elementStart(0, 'div', ['dir', ''], ['dir', 'dir']); | 
					
						
							|  |  |  |           { text(2); } | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |           const tmp = reference(1) as any; | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           textBinding(2, bind(tmp.value)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 3, 1, [Directive]); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |       expect(fixture.html).toEqual('<div dir="">Created</div>'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |   describe('directive injection', () => { | 
					
						
							|  |  |  |     let log: string[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class DirB { | 
					
						
							|  |  |  |       value = 'DirB'; | 
					
						
							|  |  |  |       constructor() { log.push(this.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |         selectors: [['', 'dirB', '']], | 
					
						
							|  |  |  |         type: DirB, | 
					
						
							|  |  |  |         factory: () => new DirB(), | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |         inputs: {value: 'value'} | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => log = []); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     it('should create directive with intra view dependencies', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         value: string = 'DirA'; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = | 
					
						
							|  |  |  |             defineDirective({type: DirA, selectors: [['', 'dirA', '']], factory: () => new DirA()}); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       class DirC { | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         value: string; | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         constructor(a: DirA, b: DirB) { this.value = a.value + b.value; } | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           type: DirC, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'dirC', '']], | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           factory: () => new DirC(directiveInject(DirA), directiveInject(DirB)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['dirC'] | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |       /** | 
					
						
							|  |  |  |        * <div dirA> | 
					
						
							|  |  |  |        *  <span dirB dirC #dir="dirC"> {{ dir.value }} </span> | 
					
						
							|  |  |  |        * </div> | 
					
						
							|  |  |  |        */ | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |           elementStart(0, 'div', ['dirA', '']); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |           { | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |             elementStart(1, 'span', ['dirB', '', 'dirC', ''], ['dir', 'dirC']); | 
					
						
							|  |  |  |             { text(3); } | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |             elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |           const tmp = reference(2) as any; | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           textBinding(3, bind(tmp.value)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 4, 1, [DirA, DirB, DirC]); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |       expect(fixture.html).toEqual('<div dira=""><span dirb="" dirc="">DirADirB</span></div>'); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |     it('should instantiate injected directives in dependency order', () => { | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dir: DirB) { log.push(`DirA (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB)), | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dirA dirB></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dirA', '', 'dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual(['DirB', 'DirA (dep: DirB)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |     it('should fallback to the module injector', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dir: DirB) { log.push(`DirA (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB)), | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // `<div dirB></div><div dirA></div>`
 | 
					
						
							|  |  |  |       // - dirB is know to the node injectors (it uses the diPublic feature)
 | 
					
						
							|  |  |  |       // - then when dirA tries to inject dirB, it will check the node injector first tree
 | 
					
						
							|  |  |  |       // - if not found, it will check the module injector tree
 | 
					
						
							|  |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dirB', '']); | 
					
						
							|  |  |  |           element(1, 'div', ['dirA', '']); | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 2, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const fakeModuleInjector: any = { | 
					
						
							|  |  |  |         get: function(token: any) { | 
					
						
							|  |  |  |           const value = token === DirB ? 'module' : 'fail'; | 
					
						
							|  |  |  |           return {value: value}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       new ComponentFixture(App, {injector: fakeModuleInjector}); | 
					
						
							|  |  |  |       expect(log).toEqual(['DirB', 'DirA (dep: module)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     it('should instantiate injected directives before components', () => { | 
					
						
							|  |  |  |       class Comp { | 
					
						
							|  |  |  |         constructor(dir: DirB) { log.push(`Comp (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |           selectors: [['comp']], | 
					
						
							|  |  |  |           type: Comp, | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |           consts: 0, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           factory: () => new Comp(directiveInject(DirB)), | 
					
						
							| 
									
										
										
										
											2019-02-09 22:51:29 +01:00
										 |  |  |           template: (rf: RenderFlags, ctx: Comp) => {} | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <comp dirB></comp> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'comp', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [Comp, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual(['DirB', 'Comp (dep: DirB)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should inject directives in the correct order in a for loop', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dir: DirB) { log.push(`DirA (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB)) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** | 
					
						
							|  |  |  |        * % for(let i = 0; i < 3; i++) { | 
					
						
							|  |  |  |        *   <div dirA dirB></div> | 
					
						
							|  |  |  |        * % } | 
					
						
							|  |  |  |        */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           container(0); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           containerRefreshStart(0); | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             for (let i = 0; i < 3; i++) { | 
					
						
							|  |  |  |               if (embeddedViewStart(0, 1, 0)) { | 
					
						
							|  |  |  |                 element(0, 'div', ['dirA', '', 'dirB', '']); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual( | 
					
						
							|  |  |  |           ['DirB', 'DirA (dep: DirB)', 'DirB', 'DirA (dep: DirB)', 'DirB', 'DirA (dep: DirB)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should instantiate directives with multiple out-of-order dependencies', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         value = 'DirA'; | 
					
						
							|  |  |  |         constructor() { log.push(this.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = | 
					
						
							|  |  |  |             defineDirective({selectors: [['', 'dirA', '']], type: DirA, factory: () => new DirA()}); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirB { | 
					
						
							|  |  |  |         constructor(dirA: DirA, dirC: DirC) { | 
					
						
							|  |  |  |           log.push(`DirB (deps: ${dirA.value} and ${dirC.value})`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirB', '']], | 
					
						
							|  |  |  |           type: DirB, | 
					
						
							|  |  |  |           factory: () => new DirB(directiveInject(DirA), directiveInject(DirC)) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirC { | 
					
						
							|  |  |  |         value = 'DirC'; | 
					
						
							|  |  |  |         constructor() { log.push(this.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = | 
					
						
							|  |  |  |             defineDirective({selectors: [['', 'dirC', '']], type: DirC, factory: () => new DirC()}); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dirA dirB dirC></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dirA', '', 'dirB', '', 'dirC', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [DirA, DirB, DirC]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual(['DirA', 'DirC', 'DirB (deps: DirA and DirC)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should instantiate in the correct order for complex case', () => { | 
					
						
							|  |  |  |       class Comp { | 
					
						
							|  |  |  |         constructor(dir: DirD) { log.push(`Comp (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |           selectors: [['comp']], | 
					
						
							|  |  |  |           type: Comp, | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |           consts: 0, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           factory: () => new Comp(directiveInject(DirD)), | 
					
						
							|  |  |  |           template: (ctx: any, fm: boolean) => {} | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         value = 'DirA'; | 
					
						
							|  |  |  |         constructor(dir: DirC) { log.push(`DirA (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new DirA(directiveInject(DirC)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirC { | 
					
						
							|  |  |  |         value = 'DirC'; | 
					
						
							|  |  |  |         constructor(dir: DirB) { log.push(`DirC (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirC', '']], | 
					
						
							|  |  |  |           type: DirC, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new DirC(directiveInject(DirB)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirD { | 
					
						
							|  |  |  |         value = 'DirD'; | 
					
						
							|  |  |  |         constructor(dir: DirA) { log.push(`DirD (dep: ${dir.value})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirD', '']], | 
					
						
							|  |  |  |           type: DirD, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new DirD(directiveInject(DirA)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <comp dirA dirB dirC dirD></comp> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'comp', ['dirA', '', 'dirB', '', 'dirC', '', 'dirD', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [Comp, DirA, DirB, DirC, DirD]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual( | 
					
						
							|  |  |  |           ['DirB', 'DirC (dep: DirB)', 'DirA (dep: DirC)', 'DirD (dep: DirA)', 'Comp (dep: DirD)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should instantiate in correct order with mixed parent and peer dependencies', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dirB: DirB, app: App) { | 
					
						
							|  |  |  |           log.push(`DirA (deps: ${dirB.value} and ${app.value})`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB), directiveInject(App)), | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class App { | 
					
						
							|  |  |  |         value = 'App'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |           selectors: [['app']], | 
					
						
							|  |  |  |           type: App, | 
					
						
							|  |  |  |           factory: () => new App(), | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |           consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |           /** <div dirA dirB dirC></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           template: (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |               element(0, 'div', ['dirA', '', 'dirB', '', 'dirC', 'dirC']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           }, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           directives: [DirA, DirB] | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual(['DirB', 'DirA (deps: DirB and App)']); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should not use a parent when peer dep is available', () => { | 
					
						
							|  |  |  |       let count = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dirB: DirB) { log.push(`DirA (dep: DirB - ${dirB.count})`); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB)), | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirB { | 
					
						
							|  |  |  |         count: number; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         constructor() { | 
					
						
							|  |  |  |           log.push(`DirB`); | 
					
						
							|  |  |  |           this.count = count++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = | 
					
						
							|  |  |  |             defineDirective({selectors: [['', 'dirB', '']], type: DirB, factory: () => new DirB()}); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dirA dirB></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dirA', '', 'dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /** <parent dirB></parent> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'parent', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [Parent, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       expect(log).toEqual(['DirB', 'DirB', 'DirA (dep: DirB - 2)']); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |     describe('dependencies in parent views', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         injector: Injector; | 
					
						
							|  |  |  |         constructor(public dirB: DirB, public vcr: ViewContainerRef) { | 
					
						
							|  |  |  |           this.injector = vcr.injector; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           factory: () => new DirA(directiveInject(DirB), directiveInject(ViewContainerRef as any)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['dirA'] | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** | 
					
						
							|  |  |  |        * <div dirA #dir="dirA"> | 
					
						
							|  |  |  |        *    {{ dir.dirB.value }} | 
					
						
							|  |  |  |        * </div> | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       const Comp = createComponent('comp', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           elementStart(0, 'div', ['dirA', ''], ['dir', 'dirA']); | 
					
						
							|  |  |  |           { text(2); } | 
					
						
							|  |  |  |           elementEnd(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           const dir = reference(1) as DirA; | 
					
						
							|  |  |  |           textBinding(2, bind(dir.dirB.value)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }, 3, 1, [DirA]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should find dependencies on component hosts', () => { | 
					
						
							|  |  |  |         /** <comp dirB>/comp> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'comp', ['dirB', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 1, 0, [Comp, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`DirB`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should find dependencies for directives in embedded views', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function IfTemplate(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div'); | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               elementStart(1, 'div', ['dirA', ''], ['dir', 'dirA']); | 
					
						
							|  |  |  |               { text(3); } | 
					
						
							|  |  |  |               elementEnd(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             const dir = reference(2) as DirA; | 
					
						
							|  |  |  |             textBinding(3, bind(dir.dirB.value)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB> | 
					
						
							|  |  |  |          *    <div *ngIf="showing"> | 
					
						
							|  |  |  |          *       <div dirA #dir="dirA"> {{ dir.dirB.value }} </div> | 
					
						
							|  |  |  |          *    </div> | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |             { template(1, IfTemplate, 4, 1, 'div', [AttributeMarker.Template, 'ngIf']); } | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             elementProperty(1, 'ngIf', bind(ctx.showing)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 2, 1, [DirA, DirB, NgIf]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         fixture.component.showing = true; | 
					
						
							|  |  |  |         fixture.update(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`DirB`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should find dependencies of directives nested deeply in inline views', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB> | 
					
						
							|  |  |  |          *     % if (!skipContent) { | 
					
						
							|  |  |  |          *        % if (!skipContent2) { | 
					
						
							|  |  |  |          *           <div dirA #dir="dirA"> {{ dir.dirB.value }} </div> | 
					
						
							|  |  |  |          *        % } | 
					
						
							|  |  |  |          *     % } | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirB', '']); | 
					
						
							|  |  |  |             { container(1); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             containerRefreshStart(1); | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               if (!ctx.skipContent) { | 
					
						
							|  |  |  |                 let rf1 = embeddedViewStart(0, 1, 0); | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   if (rf1 & RenderFlags.Create) { | 
					
						
							|  |  |  |                     container(0); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                   if (rf1 & RenderFlags.Update) { | 
					
						
							|  |  |  |                     containerRefreshStart(0); | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                       if (!ctx.skipContent2) { | 
					
						
							|  |  |  |                         let rf2 = embeddedViewStart(0, 3, 1); | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                           if (rf2 & RenderFlags.Create) { | 
					
						
							|  |  |  |                             elementStart(0, 'div', ['dirA', ''], ['dir', 'dirA']); | 
					
						
							|  |  |  |                             { text(2); } | 
					
						
							|  |  |  |                             elementEnd(); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                           if (rf2 & RenderFlags.Update) { | 
					
						
							|  |  |  |                             const dir = reference(1) as DirA; | 
					
						
							|  |  |  |                             textBinding(2, bind(dir.dirB.value)); | 
					
						
							|  |  |  |                           } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         embeddedViewEnd(); | 
					
						
							|  |  |  |                       } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     containerRefreshEnd(); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 embeddedViewEnd(); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             containerRefreshEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 2, 0, [DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`DirB`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should find dependencies in declaration tree of ng-template (not insertion tree)', () => { | 
					
						
							|  |  |  |         let structuralDir !: StructuralDir; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class StructuralDir { | 
					
						
							|  |  |  |           // @Input()
 | 
					
						
							|  |  |  |           tmp !: TemplateRef<any>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           constructor(public vcr: ViewContainerRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           create() { this.vcr.createEmbeddedView(this.tmp); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: StructuralDir, | 
					
						
							|  |  |  |             selectors: [['', 'structuralDir', '']], | 
					
						
							|  |  |  |             factory: () => structuralDir = | 
					
						
							|  |  |  |                          new StructuralDir(directiveInject(ViewContainerRef as any)), | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |             inputs: {tmp: 'tmp'} | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function FooTemplate(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirA', ''], ['dir', 'dirA']); | 
					
						
							|  |  |  |             { text(2); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             const dir = reference(1) as DirA; | 
					
						
							|  |  |  |             textBinding(2, bind(dir.dirB.value)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB value="declaration"> | 
					
						
							|  |  |  |          *   <ng-template #foo> | 
					
						
							|  |  |  |          *       <div dirA dir="dirA"> {{ dir.dirB.value }} </div> | 
					
						
							|  |  |  |          *   </ng-template> | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          * | 
					
						
							|  |  |  |          * <div dirB value="insertion"> | 
					
						
							|  |  |  |          *   <div structuralDir [tmp]="foo"></div> | 
					
						
							|  |  |  |          *   // insertion point
 | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirB', '', 'value', 'declaration']); | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |             { | 
					
						
							|  |  |  |               template( | 
					
						
							|  |  |  |                   1, FooTemplate, 3, 1, 'ng-template', null, ['foo', ''], templateRefExtractor); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |             elementEnd(); | 
					
						
							|  |  |  |             elementStart(3, 'div', ['dirB', '', 'value', 'insertion']); | 
					
						
							|  |  |  |             { element(4, 'div', ['structuralDir', '']); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             const foo = reference(2) as any; | 
					
						
							|  |  |  |             elementProperty(4, 'tmp', bind(foo)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 5, 1, [DirA, DirB, StructuralDir]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         structuralDir.create(); | 
					
						
							|  |  |  |         fixture.update(); | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`declaration`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should create injectors on second template pass', () => { | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <comp dirB></comp> | 
					
						
							|  |  |  |          * <comp dirB></comp> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'comp', ['dirB', '']); | 
					
						
							|  |  |  |             element(1, 'comp', ['dirB', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 2, 0, [Comp, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`DirBDirB`); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should create injectors and host bindings in same view', () => { | 
					
						
							|  |  |  |         let hostBindingDir !: HostBindingDir; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class HostBindingDir { | 
					
						
							|  |  |  |           // @HostBinding('id')
 | 
					
						
							|  |  |  |           id = 'foo'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: HostBindingDir, | 
					
						
							|  |  |  |             selectors: [['', 'hostBindingDir', '']], | 
					
						
							|  |  |  |             factory: () => hostBindingDir = new HostBindingDir(), | 
					
						
							| 
									
										
										
										
											2018-11-20 15:20:19 -08:00
										 |  |  |             hostBindings: (rf: RenderFlags, ctx: any, elementIndex: number) => { | 
					
						
							| 
									
										
										
										
											2018-11-27 12:05:26 -08:00
										 |  |  |               if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                 allocHostVars(1); | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2018-11-20 15:20:19 -08:00
										 |  |  |               if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                 elementProperty(elementIndex, 'id', bind(ctx.id)); | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2018-09-28 21:26:45 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let dir !: DirA; | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB hostBindingDir> | 
					
						
							|  |  |  |          *     <p dirA #dir="dirA"> | 
					
						
							|  |  |  |          *         {{ dir.dirB.value }} | 
					
						
							|  |  |  |          *     </p> | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', [ | 
					
						
							|  |  |  |               'dirB', | 
					
						
							|  |  |  |               '', | 
					
						
							|  |  |  |               'hostBindingDir', | 
					
						
							|  |  |  |               '', | 
					
						
							|  |  |  |             ]); | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               elementStart(1, 'p', ['dirA', ''], ['dir', 'dirA']); | 
					
						
							|  |  |  |               { text(3); } | 
					
						
							|  |  |  |               elementEnd(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             dir = reference(2) as DirA; | 
					
						
							|  |  |  |             textBinding(3, bind(dir.dirB.value)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 4, 1, [HostBindingDir, DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(fixture.hostElement.textContent).toEqual(`DirB`); | 
					
						
							|  |  |  |         const hostDirEl = fixture.hostElement.querySelector('div') as HTMLElement; | 
					
						
							|  |  |  |         expect(hostDirEl.id).toEqual('foo'); | 
					
						
							|  |  |  |         // The injector should not be overwritten by host bindings
 | 
					
						
							|  |  |  |         expect(dir.vcr.injector).toEqual(dir.injector); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         hostBindingDir.id = 'bar'; | 
					
						
							|  |  |  |         fixture.update(); | 
					
						
							|  |  |  |         expect(hostDirEl.id).toEqual('bar'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 15:54:16 -07:00
										 |  |  |     it('should create instance even when no injector present', () => { | 
					
						
							|  |  |  |       class MyService { | 
					
						
							|  |  |  |         value = 'MyService'; | 
					
						
							|  |  |  |         static ngInjectableDef = | 
					
						
							|  |  |  |             defineInjectable({providedIn: 'root', factory: () => new MyService()}); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         constructor(public myService: MyService) {} | 
					
						
							|  |  |  |         static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |           type: MyComponent, | 
					
						
							|  |  |  |           selectors: [['my-component']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |           consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           vars: 1, | 
					
						
							| 
									
										
										
										
											2018-04-12 15:54:16 -07:00
										 |  |  |           factory: () => new MyComponent(directiveInject(MyService)), | 
					
						
							|  |  |  |           template: function(rf: RenderFlags, ctx: MyComponent) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               text(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |               textBinding(0, bind(ctx.myService.value)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const fixture = new ComponentFixture(MyComponent); | 
					
						
							|  |  |  |       fixture.update(); | 
					
						
							|  |  |  |       expect(fixture.html).toEqual('MyService'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |     it('should throw if directive is not found anywhere', () => { | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       class Dir { | 
					
						
							|  |  |  |         constructor(siblingDir: OtherDir) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |           type: Dir, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new Dir(directiveInject(OtherDir)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class OtherDir { | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = defineDirective( | 
					
						
							|  |  |  |             {selectors: [['', 'other', '']], type: OtherDir, factory: () => new OtherDir()}); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dir></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dir', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [Dir, OtherDir]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 15:54:16 -07:00
										 |  |  |       expect(() => new ComponentFixture(App)).toThrowError(/Injector: NOT_FOUND \[OtherDir\]/); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |     it('should throw if directive is not found in ancestor tree', () => { | 
					
						
							|  |  |  |       class Dir { | 
					
						
							|  |  |  |         constructor(siblingDir: OtherDir) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |           type: Dir, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new Dir(directiveInject(OtherDir)) | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class OtherDir { | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         static ngDirectiveDef = defineDirective( | 
					
						
							|  |  |  |             {selectors: [['', 'other', '']], type: OtherDir, factory: () => new OtherDir()}); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** | 
					
						
							|  |  |  |        * <div other></div> | 
					
						
							|  |  |  |        * <div dir></div> | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['other', '']); | 
					
						
							|  |  |  |           element(1, 'div', ['dir', '']); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 2, 0, [Dir, OtherDir]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       expect(() => new ComponentFixture(App)).toThrowError(/Injector: NOT_FOUND \[OtherDir\]/); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     it('should throw if directives try to inject each other', () => { | 
					
						
							|  |  |  |       class DirA { | 
					
						
							|  |  |  |         constructor(dir: DirB) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |           type: DirA, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new DirA(directiveInject(DirB)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirB { | 
					
						
							|  |  |  |         constructor(dir: DirA) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dirB', '']], | 
					
						
							|  |  |  |           type: DirB, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new DirB(directiveInject(DirA)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dirA dirB></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dirA', '', 'dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |       expect(() => new ComponentFixture(App)).toThrowError(/Circular dep for/); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw if directive tries to inject itself', () => { | 
					
						
							|  |  |  |       class Dir { | 
					
						
							|  |  |  |         constructor(dir: Dir) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |           type: Dir, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           factory: () => new Dir(directiveInject(Dir)) | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div dir></div> */ | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |           element(0, 'div', ['dir', '']); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 1, 0, [Dir]); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |       expect(() => new ComponentFixture(App)).toThrowError(/Circular dep for/); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |     describe('flags', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirB { | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |         // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |         value !: string; | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: DirB, | 
					
						
							|  |  |  |           selectors: [['', 'dirB', '']], | 
					
						
							|  |  |  |           factory: () => new DirB(), | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           inputs: {value: 'dirB'} | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |       describe('Optional', () => { | 
					
						
							|  |  |  |         let dirA: DirA|null = null; | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class DirA { | 
					
						
							|  |  |  |           constructor(@Optional() public dirB: DirB|null) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirA, | 
					
						
							|  |  |  |             selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |             factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.Optional)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |         beforeEach(() => dirA = null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not throw if dependency is @Optional (limp mode)', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /** <div dirA></div> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirA', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { new ComponentFixture(App); }).not.toThrow(); | 
					
						
							|  |  |  |           expect(dirA !.dirB).toEqual(null); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not throw if dependency is @Optional (module injector)', () => { | 
					
						
							|  |  |  |           class SomeModule { | 
					
						
							|  |  |  |             static ngInjectorDef = defineInjector({factory: () => new SomeModule()}); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |           /** <div dirA></div> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirA', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             const injector = createInjector(SomeModule); | 
					
						
							|  |  |  |             new ComponentFixture(App, {injector}); | 
					
						
							|  |  |  |           }).not.toThrow(); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           expect(dirA !.dirB).toEqual(null); | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |         it('should return null if @Optional dependency has @Self flag', () => { | 
					
						
							|  |  |  |           let dirC !: DirC; | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |           class DirC { | 
					
						
							|  |  |  |             constructor(@Optional() @Self() public dirB: DirB|null) {} | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |             static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |               type: DirC, | 
					
						
							|  |  |  |               selectors: [['', 'dirC', '']], | 
					
						
							|  |  |  |               factory: () => dirC = | 
					
						
							|  |  |  |                            new DirC(directiveInject(DirB, InjectFlags.Optional|InjectFlags.Self)) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |           /** <div dirC></div> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirC', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirC, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { new ComponentFixture(App); }).not.toThrow(); | 
					
						
							|  |  |  |           expect(dirC !.dirB).toEqual(null); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not throw if dependency is @Optional but defined elsewhere', () => { | 
					
						
							|  |  |  |           let dirA: DirA; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           class DirA { | 
					
						
							|  |  |  |             constructor(@Optional() public dirB: DirB|null) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |               type: DirA, | 
					
						
							|  |  |  |               selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |               factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.Optional)) | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:35:51 -07:00
										 |  |  |           /** | 
					
						
							|  |  |  |            * <div dirB></div> | 
					
						
							|  |  |  |            * <div dirA></div> | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirB', '']); | 
					
						
							|  |  |  |               element(1, 'div', ['dirA', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 2, 0, [DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             new ComponentFixture(App); | 
					
						
							|  |  |  |             expect(dirA !.dirB).toEqual(null); | 
					
						
							|  |  |  |           }).not.toThrow(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should skip the current node with @SkipSelf', () => { | 
					
						
							|  |  |  |         let dirA: DirA; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class DirA { | 
					
						
							|  |  |  |           constructor(@SkipSelf() public dirB: DirB) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirA, | 
					
						
							|  |  |  |             selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |             factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.SkipSelf)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** <div dirA dirB="self"></div> */ | 
					
						
							|  |  |  |         const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |             element(0, 'div', ['dirA', '', 'dirB', 'self']); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         }, 1, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* <comp dirB="parent"></comp> */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |             element(0, 'comp', ['dirB', 'parent']); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         }, 1, 0, [Comp, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |         new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |         expect(dirA !.dirB.value).toEqual('parent'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should check only the current node with @Self', () => { | 
					
						
							|  |  |  |         let dirA: DirA; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class DirA { | 
					
						
							|  |  |  |           constructor(@Self() public dirB: DirB) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirA, | 
					
						
							|  |  |  |             selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |             factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.Self)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB> | 
					
						
							|  |  |  |          *   <div dirA></div> | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |             element(1, 'div', ['dirA', '']); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         }, 2, 0, [DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         expect(() => { | 
					
						
							|  |  |  |           new ComponentFixture(App); | 
					
						
							|  |  |  |         }).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should check only the current node with @Self even with false positive', () => { | 
					
						
							|  |  |  |         let dirA: DirA; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class DirA { | 
					
						
							|  |  |  |           constructor(@Self() public dirB: DirB) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirA, | 
					
						
							|  |  |  |             selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |             factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.Self)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const DirC = createDirective('dirC'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * <div dirB> | 
					
						
							|  |  |  |          *   <div dirA dirC></div> | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2018-07-27 12:55:17 -07:00
										 |  |  |             element(1, 'div', ['dirA', '', 'dirC', '']); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         }, 2, 0, [DirA, DirB, DirC]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(() => { | 
					
						
							|  |  |  |           (DirA as any)['__NG_ELEMENT_ID__'] = 1; | 
					
						
							|  |  |  |           (DirC as any)['__NG_ELEMENT_ID__'] = 257; | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |           new ComponentFixture(App); | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         }).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |       describe('@Host', () => { | 
					
						
							|  |  |  |         let dirA: DirA|null = null; | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  |         let dirString: DirString|null = null; | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           dirA = null; | 
					
						
							|  |  |  |           dirString = null; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class DirA { | 
					
						
							|  |  |  |           constructor(@Host() public dirB: DirB) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirA, | 
					
						
							|  |  |  |             selectors: [['', 'dirA', '']], | 
					
						
							|  |  |  |             factory: () => dirA = new DirA(directiveInject(DirB, InjectFlags.Host)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  |         class DirString { | 
					
						
							|  |  |  |           constructor(@Host() public s: String) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirString, | 
					
						
							|  |  |  |             selectors: [['', 'dirString', '']], | 
					
						
							|  |  |  |             factory: () => dirString = new DirString(directiveInject(String, InjectFlags.Host)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should find viewProviders on the host itself', () => { | 
					
						
							|  |  |  |           /** <div dirString></div> */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirString', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirString], [], null, [], [{provide: String, useValue: 'Foo'}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* <comp></comp> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'comp'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [Comp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           new ComponentFixture(App); | 
					
						
							|  |  |  |           expect(dirString !.s).toEqual('Foo'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should find host component on the host itself', () => { | 
					
						
							|  |  |  |           let dirComp: DirComp|null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           class DirComp { | 
					
						
							|  |  |  |             constructor(@Host() public comp: any) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |               type: DirComp, | 
					
						
							|  |  |  |               selectors: [['', 'dirCmp', '']], | 
					
						
							|  |  |  |               factory: () => dirComp = new DirComp(directiveInject(Comp, InjectFlags.Host)) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /** <div dirCmp></div> */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirCmp', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirComp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* <comp></comp> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'comp'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [Comp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           new ComponentFixture(App); | 
					
						
							|  |  |  |           expect(dirComp !.comp instanceof Comp).toBeTruthy(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not find providers on the host itself', () => { | 
					
						
							|  |  |  |           /** <div dirString></div> */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirString', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirString], [], null, [{provide: String, useValue: 'Foo'}]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* <comp></comp> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'comp'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [Comp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             new ComponentFixture(App); | 
					
						
							|  |  |  |           }).toThrowError(/NodeInjector: NOT_FOUND \[String\]/); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not find other directives on the host itself', () => { | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           /** <div dirA></div> */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirA', '']); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  |           }, 1, 0, [DirA]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           /* <comp dirB></comp> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'comp', ['dirB', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [Comp, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             new ComponentFixture(App); | 
					
						
							|  |  |  |           }).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  |         it('should not find providers on the host itself if in inline view', () => { | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           let comp !: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /** | 
					
						
							|  |  |  |            * % if (showing) { | 
					
						
							|  |  |  |            *   <div dirA></div> | 
					
						
							|  |  |  |            * % } | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               container(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |               containerRefreshStart(0); | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 if (ctx.showing) { | 
					
						
							|  |  |  |                   let rf1 = embeddedViewStart(0, 1, 0); | 
					
						
							|  |  |  |                   if (rf1 & RenderFlags.Create) { | 
					
						
							|  |  |  |                     element(0, 'div', ['dirA', '']); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                   embeddedViewEnd(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               containerRefreshEnd(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirA, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* <comp dirB></comp> */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'comp', ['dirB', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |               comp = getDirectiveOnNode(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [Comp, DirB]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             comp.showing = true; | 
					
						
							|  |  |  |             fixture.update(); | 
					
						
							|  |  |  |           }).toThrowError(/NodeInjector: NOT_FOUND \[DirB\]/); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should find providers across embedded views if not passing component boundary', () => { | 
					
						
							|  |  |  |           let dirB !: DirB; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           function IfTemplate(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirA', '']); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           /** | 
					
						
							|  |  |  |            * <div dirB> | 
					
						
							|  |  |  |            *   <div *ngIf="showing" dirA></div> | 
					
						
							|  |  |  |            * </div> | 
					
						
							|  |  |  |            */ | 
					
						
							|  |  |  |           const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               elementStart(0, 'div', ['dirB', '']); | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |               { | 
					
						
							|  |  |  |                 template( | 
					
						
							|  |  |  |                     1, IfTemplate, 1, 0, 'div', ['dirA', '', AttributeMarker.Template, 'ngIf']); | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |               elementEnd(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |               elementProperty(1, 'ngIf', bind(ctx.showing)); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |               // testing only
 | 
					
						
							|  |  |  |               dirB = getDirectiveOnNode(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 2, 1, [NgIf, DirA, DirB]); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |           fixture.component.showing = true; | 
					
						
							|  |  |  |           fixture.update(); | 
					
						
							| 
									
										
										
										
											2018-04-23 18:24:40 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |           expect(dirA !.dirB).toEqual(dirB); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-12-13 11:14:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         it('should not find component above the host', () => { | 
					
						
							|  |  |  |           let dirComp: DirComp|null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           class DirComp { | 
					
						
							|  |  |  |             constructor(@Host() public comp: any) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |               type: DirComp, | 
					
						
							|  |  |  |               selectors: [['', 'dirCmp', '']], | 
					
						
							|  |  |  |               factory: () => dirComp = new DirComp(directiveInject(App, InjectFlags.Host)) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /** <div dirCmp></div> */ | 
					
						
							|  |  |  |           const Comp = createComponent('comp', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               element(0, 'div', ['dirCmp', '']); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }, 1, 0, [DirComp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /* <comp></comp> */ | 
					
						
							|  |  |  |           class App { | 
					
						
							|  |  |  |             static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |               type: App, | 
					
						
							|  |  |  |               selectors: [['app']], | 
					
						
							|  |  |  |               consts: 1, | 
					
						
							|  |  |  |               vars: 0, | 
					
						
							|  |  |  |               factory: () => new App, | 
					
						
							|  |  |  |               template: function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |                 if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                   element(0, 'comp'); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               directives: [Comp], | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(() => { | 
					
						
							|  |  |  |             new ComponentFixture(App); | 
					
						
							|  |  |  |           }).toThrowError(/NodeInjector: NOT_FOUND \[App\]/); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         describe('regression', () => { | 
					
						
							|  |  |  |           // based on https://stackblitz.com/edit/angular-riss8k?file=src/app/app.component.ts
 | 
					
						
							|  |  |  |           it('should allow directives with Host flag to inject view providers from containing component', | 
					
						
							|  |  |  |              () => { | 
					
						
							|  |  |  |                let controlContainers: ControlContainer[] = []; | 
					
						
							|  |  |  |                let injectedControlContainer: ControlContainer|null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                class ControlContainer {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                /* | 
					
						
							|  |  |  |                @Directive({ | 
					
						
							|  |  |  |                  selector: '[group]', | 
					
						
							|  |  |  |                  providers: [{provide: ControlContainer, useExisting: GroupDirective}] | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                */ | 
					
						
							|  |  |  |                class GroupDirective { | 
					
						
							|  |  |  |                  constructor() { controlContainers.push(this); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                  static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |                    type: GroupDirective, | 
					
						
							|  |  |  |                    selectors: [['', 'group', '']], | 
					
						
							|  |  |  |                    factory: () => new GroupDirective(), | 
					
						
							|  |  |  |                    features: [ProvidersFeature( | 
					
						
							|  |  |  |                        [{provide: ControlContainer, useExisting: GroupDirective}])], | 
					
						
							|  |  |  |                  }); | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                // @Directive({selector: '[controlName]'})
 | 
					
						
							|  |  |  |                class ControlNameDirective { | 
					
						
							|  |  |  |                  constructor(@Host() @SkipSelf() @Inject(ControlContainer) parent: | 
					
						
							|  |  |  |                                  ControlContainer) { | 
					
						
							|  |  |  |                    injectedControlContainer = parent; | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                  static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |                    type: ControlNameDirective, | 
					
						
							|  |  |  |                    selectors: [['', 'controlName', '']], | 
					
						
							|  |  |  |                    factory: () => new ControlNameDirective(directiveInject( | 
					
						
							|  |  |  |                                 ControlContainer, InjectFlags.Host|InjectFlags.SkipSelf)) | 
					
						
							|  |  |  |                  }); | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                /* | 
					
						
							|  |  |  |                @Component({ | 
					
						
							|  |  |  |                  selector: 'child', | 
					
						
							|  |  |  |                  template: `
 | 
					
						
							|  |  |  |                    <input controlName type="text"> | 
					
						
							|  |  |  |                  `,
 | 
					
						
							|  |  |  |                  viewProviders: [{provide: ControlContainer, useExisting: GroupDirective}] | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                */ | 
					
						
							|  |  |  |                class ChildComponent { | 
					
						
							|  |  |  |                  static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |                    type: ChildComponent, | 
					
						
							|  |  |  |                    selectors: [['child']], | 
					
						
							|  |  |  |                    consts: 1, | 
					
						
							|  |  |  |                    vars: 0, | 
					
						
							|  |  |  |                    factory: () => new ChildComponent(), | 
					
						
							|  |  |  |                    template: function(rf: RenderFlags, ctx: ChildComponent) { | 
					
						
							|  |  |  |                      if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                        element(0, 'input', ['controlName', '', 'type', 'text']); | 
					
						
							|  |  |  |                      } | 
					
						
							|  |  |  |                    }, | 
					
						
							|  |  |  |                    directives: [ControlNameDirective], | 
					
						
							|  |  |  |                    features: [ProvidersFeature( | 
					
						
							|  |  |  |                        [], [{provide: ControlContainer, useExisting: GroupDirective}])], | 
					
						
							|  |  |  |                  }); | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  |                /* | 
					
						
							|  |  |  |                @Component({ | 
					
						
							|  |  |  |                  selector: 'my-app', | 
					
						
							|  |  |  |                  template: `
 | 
					
						
							|  |  |  |                    <div group> | 
					
						
							|  |  |  |                      <child></child> | 
					
						
							|  |  |  |                    </div> | 
					
						
							|  |  |  |                  `
 | 
					
						
							|  |  |  |                }) | 
					
						
							|  |  |  |                */ | 
					
						
							|  |  |  |                class AppComponent { | 
					
						
							|  |  |  |                  static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |                    type: AppComponent, | 
					
						
							|  |  |  |                    selectors: [['my-app']], | 
					
						
							|  |  |  |                    consts: 2, | 
					
						
							|  |  |  |                    vars: 0, | 
					
						
							|  |  |  |                    factory: () => new AppComponent(), | 
					
						
							|  |  |  |                    template: function(rf: RenderFlags, ctx: AppComponent) { | 
					
						
							|  |  |  |                      if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                        elementStart(0, 'div', ['group', '']); | 
					
						
							|  |  |  |                        element(1, 'child'); | 
					
						
							|  |  |  |                        elementEnd(); | 
					
						
							|  |  |  |                      } | 
					
						
							|  |  |  |                    }, | 
					
						
							|  |  |  |                    directives: [ChildComponent, GroupDirective] | 
					
						
							|  |  |  |                  }); | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                const fixture = new ComponentFixture(AppComponent as ComponentType<AppComponent>); | 
					
						
							|  |  |  |                expect(fixture.html) | 
					
						
							|  |  |  |                    .toEqual( | 
					
						
							|  |  |  |                        '<div group=""><child><input controlname="" type="text"></child></div>'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                expect(controlContainers).toEqual([injectedControlContainer !]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-10-26 19:12:24 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |   describe('Special tokens', () => { | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-23 14:28:15 -07:00
										 |  |  |     describe('Injector', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should inject the injector', () => { | 
					
						
							|  |  |  |         let injectorDir !: InjectorDir; | 
					
						
							|  |  |  |         let otherInjectorDir !: OtherInjectorDir; | 
					
						
							|  |  |  |         let divElement !: HTMLElement; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class InjectorDir { | 
					
						
							|  |  |  |           constructor(public injector: Injector) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: InjectorDir, | 
					
						
							|  |  |  |             selectors: [['', 'injectorDir', '']], | 
					
						
							|  |  |  |             factory: () => injectorDir = new InjectorDir(directiveInject(Injector as any)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class OtherInjectorDir { | 
					
						
							|  |  |  |           constructor(public otherDir: InjectorDir, public injector: Injector) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: OtherInjectorDir, | 
					
						
							|  |  |  |             selectors: [['', 'otherInjectorDir', '']], | 
					
						
							|  |  |  |             factory: () => otherInjectorDir = new OtherInjectorDir( | 
					
						
							|  |  |  |                          directiveInject(InjectorDir), directiveInject(Injector as any)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** <div injectorDir otherInjectorDir></div> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'div', ['injectorDir', '', 'otherInjectorDir', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           // testing only
 | 
					
						
							|  |  |  |           divElement = load(0); | 
					
						
							|  |  |  |         }, 1, 0, [InjectorDir, OtherInjectorDir]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(injectorDir.injector.get(ElementRef).nativeElement).toBe(divElement); | 
					
						
							|  |  |  |         expect(otherInjectorDir.injector.get(ElementRef).nativeElement).toBe(divElement); | 
					
						
							|  |  |  |         expect(otherInjectorDir.injector.get(InjectorDir)).toBe(injectorDir); | 
					
						
							|  |  |  |         expect(injectorDir.injector).not.toBe(otherInjectorDir.injector); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-14 10:20:27 +01:00
										 |  |  |       it('should inject INJECTOR', () => { | 
					
						
							|  |  |  |         let injectorDir !: INJECTORDir; | 
					
						
							|  |  |  |         let divElement !: HTMLElement; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class INJECTORDir { | 
					
						
							|  |  |  |           constructor(public injector: Injector) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: INJECTORDir, | 
					
						
							|  |  |  |             selectors: [['', 'injectorDir', '']], | 
					
						
							|  |  |  |             factory: () => injectorDir = new INJECTORDir(directiveInject(INJECTOR as any)) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** <div injectorDir otherInjectorDir></div> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'div', ['injectorDir', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           // testing only
 | 
					
						
							|  |  |  |           divElement = load(0); | 
					
						
							|  |  |  |         }, 1, 0, [INJECTORDir]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(injectorDir.injector.get(ElementRef).nativeElement).toBe(divElement); | 
					
						
							|  |  |  |         expect(injectorDir.injector.get(Injector).get(ElementRef).nativeElement).toBe(divElement); | 
					
						
							|  |  |  |         expect(injectorDir.injector.get(INJECTOR).get(ElementRef).nativeElement).toBe(divElement); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-23 14:28:15 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |     describe('ElementRef', () => { | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |       it('should create directive with ElementRef dependencies', () => { | 
					
						
							|  |  |  |         let dir !: Directive; | 
					
						
							|  |  |  |         let dirSameInstance !: DirectiveSameInstance; | 
					
						
							| 
									
										
										
										
											2018-10-12 18:49:00 -07:00
										 |  |  |         let div !: RElement; | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class Directive { | 
					
						
							|  |  |  |           value: string; | 
					
						
							|  |  |  |           constructor(public elementRef: ElementRef) { | 
					
						
							|  |  |  |             this.value = (elementRef.constructor as any).name; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: Directive, | 
					
						
							|  |  |  |             selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |             factory: () => dir = new Directive(directiveInject(ElementRef)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         class DirectiveSameInstance { | 
					
						
							|  |  |  |           isSameInstance: boolean; | 
					
						
							|  |  |  |           constructor(public elementRef: ElementRef, directive: Directive) { | 
					
						
							|  |  |  |             this.isSameInstance = elementRef === directive.elementRef; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirectiveSameInstance, | 
					
						
							|  |  |  |             selectors: [['', 'dirSame', '']], | 
					
						
							|  |  |  |             factory: () => dirSameInstance = new DirectiveSameInstance( | 
					
						
							|  |  |  |                          directiveInject(ElementRef), directiveInject(Directive)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dirSame'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         /** <div dir dirSame></div> */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dir', '', 'dirSame', '']); | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							| 
									
										
										
										
											2019-02-23 11:14:35 -08:00
										 |  |  |             div = getNativeByIndex(0, getLView()) as RElement; | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           } | 
					
						
							|  |  |  |         }, 1, 0, [Directive, DirectiveSameInstance]); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         expect(dir.value).toContain('ElementRef'); | 
					
						
							| 
									
										
										
										
											2018-10-12 18:49:00 -07:00
										 |  |  |         expect(dir.elementRef.nativeElement).toEqual(div); | 
					
						
							|  |  |  |         expect(dirSameInstance.elementRef.nativeElement).toEqual(div); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         // Each ElementRef instance should be unique
 | 
					
						
							|  |  |  |         expect(dirSameInstance.isSameInstance).toBe(false); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |       it('should create ElementRef with comment if requesting directive is on <ng-template> node', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            let dir !: Directive; | 
					
						
							| 
									
										
										
										
											2018-10-11 13:13:57 -07:00
										 |  |  |            let lContainer !: LContainer; | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            class Directive { | 
					
						
							|  |  |  |              value: string; | 
					
						
							|  |  |  |              constructor(public elementRef: ElementRef) { | 
					
						
							|  |  |  |                this.value = (elementRef.constructor as any).name; | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |              static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |                type: Directive, | 
					
						
							|  |  |  |                selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |                factory: () => dir = new Directive(directiveInject(ElementRef)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |                exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |              }); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  |            } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |            /** <ng-template dir></ng-template> */ | 
					
						
							|  |  |  |            const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |              if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |                template(0, () => {}, 0, 0, 'ng-template', ['dir', '']); | 
					
						
							| 
									
										
										
										
											2018-10-11 13:13:57 -07:00
										 |  |  |                lContainer = load(0) as any; | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |              } | 
					
						
							|  |  |  |            }, 1, 0, [Directive]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |            expect(dir.value).toContain('ElementRef'); | 
					
						
							| 
									
										
										
										
											2018-10-11 13:13:57 -07:00
										 |  |  |            expect(dir.elementRef.nativeElement).toEqual(lContainer[NATIVE]); | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |          }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |     describe('TemplateRef', () => { | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  |       class Directive { | 
					
						
							|  |  |  |         value: string; | 
					
						
							|  |  |  |         constructor(public templateRef: TemplateRef<any>) { | 
					
						
							|  |  |  |           this.value = (templateRef.constructor as any).name; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: Directive, | 
					
						
							|  |  |  |           selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |           factory: () => new Directive(directiveInject(TemplateRef as any)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  |       it('should create directive with TemplateRef dependencies', () => { | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         class DirectiveSameInstance { | 
					
						
							|  |  |  |           isSameInstance: boolean; | 
					
						
							|  |  |  |           constructor(templateRef: TemplateRef<any>, directive: Directive) { | 
					
						
							|  |  |  |             this.isSameInstance = templateRef === directive.templateRef; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirectiveSameInstance, | 
					
						
							|  |  |  |             selectors: [['', 'dirSame', '']], | 
					
						
							|  |  |  |             factory: () => new DirectiveSameInstance( | 
					
						
							|  |  |  |                          directiveInject(TemplateRef as any), directiveInject(Directive)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dirSame'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         /** | 
					
						
							|  |  |  |          * <ng-template dir dirSame #dir="dir" #dirSame="dirSame"> | 
					
						
							|  |  |  |          *   {{ dir.value }} - {{ dirSame.value }} | 
					
						
							|  |  |  |          * </ng-template> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |             template( | 
					
						
							|  |  |  |                 0, function() {}, 0, 0, 'ng-template', ['dir', '', 'dirSame', ''], | 
					
						
							|  |  |  |                 ['dir', 'dir', 'dirSame', 'dirSame']); | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |             text(3); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             const tmp1 = reference(1) as any; | 
					
						
							|  |  |  |             const tmp2 = reference(2) as any; | 
					
						
							|  |  |  |             textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, '')); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 4, 2, [Directive, DirectiveSameInstance]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         // Each TemplateRef instance should be unique
 | 
					
						
							|  |  |  |         expect(fixture.html).toContain('TemplateRef'); | 
					
						
							|  |  |  |         expect(fixture.html).toContain('false'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should throw if injected on an element', () => { | 
					
						
							|  |  |  |         /** <div dir></div> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'div', ['dir', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 1, 0, [Directive]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => new ComponentFixture(App)).toThrowError(/No provider for TemplateRef/); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should throw if injected on an ng-container', () => { | 
					
						
							|  |  |  |         /** <ng-container dir></ng-container> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementContainerStart(0, ['dir', '']); | 
					
						
							|  |  |  |             elementContainerEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 1, 0, [Directive]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => new ComponentFixture(App)).toThrowError(/No provider for TemplateRef/); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should NOT throw if optional and injected on an element', () => { | 
					
						
							|  |  |  |         let dir !: OptionalDirective; | 
					
						
							|  |  |  |         class OptionalDirective { | 
					
						
							|  |  |  |           constructor(@Optional() public templateRef: TemplateRef<any>) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: OptionalDirective, | 
					
						
							|  |  |  |             selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |             factory: () => dir = new OptionalDirective( | 
					
						
							|  |  |  |                          directiveInject(TemplateRef as any, InjectFlags.Optional)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-10-25 11:18:49 -07:00
										 |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** <div dir></div> */ | 
					
						
							|  |  |  |         const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             element(0, 'div', ['dir', '']); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 1, 0, [OptionalDirective]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => new ComponentFixture(App)).not.toThrow(); | 
					
						
							|  |  |  |         expect(dir.templateRef).toBeNull(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('ViewContainerRef', () => { | 
					
						
							|  |  |  |       it('should create directive with ViewContainerRef dependencies', () => { | 
					
						
							|  |  |  |         class Directive { | 
					
						
							|  |  |  |           value: string; | 
					
						
							|  |  |  |           constructor(public viewContainerRef: ViewContainerRef) { | 
					
						
							|  |  |  |             this.value = (viewContainerRef.constructor as any).name; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: Directive, | 
					
						
							|  |  |  |             selectors: [['', 'dir', '']], | 
					
						
							|  |  |  |             factory: () => new Directive(directiveInject(ViewContainerRef as any)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class DirectiveSameInstance { | 
					
						
							|  |  |  |           isSameInstance: boolean; | 
					
						
							|  |  |  |           constructor(viewContainerRef: ViewContainerRef, directive: Directive) { | 
					
						
							|  |  |  |             this.isSameInstance = viewContainerRef === directive.viewContainerRef; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |             type: DirectiveSameInstance, | 
					
						
							|  |  |  |             selectors: [['', 'dirSame', '']], | 
					
						
							|  |  |  |             factory: () => new DirectiveSameInstance( | 
					
						
							|  |  |  |                          directiveInject(ViewContainerRef as any), directiveInject(Directive)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |             exportAs: ['dirSame'] | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         /** | 
					
						
							|  |  |  |          * <div dir dirSame #dir="dir" #dirSame="dirSame"> | 
					
						
							|  |  |  |          *   {{ dir.value }} - {{ dirSame.value }} | 
					
						
							|  |  |  |          * </div> | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart( | 
					
						
							|  |  |  |                 0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir', 'dirSame', 'dirSame']); | 
					
						
							|  |  |  |             { text(3); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             const tmp1 = reference(1) as any; | 
					
						
							|  |  |  |             const tmp2 = reference(2) as any; | 
					
						
							|  |  |  |             textBinding(3, interpolation2('', tmp1.value, '-', tmp2.isSameInstance, '')); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, 4, 2, [Directive, DirectiveSameInstance]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |         // Each ViewContainerRef instance should be unique
 | 
					
						
							|  |  |  |         expect(fixture.html).toContain('ViewContainerRef'); | 
					
						
							|  |  |  |         expect(fixture.html).toContain('false'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |     describe('ChangeDetectorRef', () => { | 
					
						
							|  |  |  |       let dir: Directive; | 
					
						
							|  |  |  |       let dirSameInstance: DirectiveSameInstance; | 
					
						
							|  |  |  |       let comp: MyComp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class MyComp { | 
					
						
							|  |  |  |         constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |           type: MyComp, | 
					
						
							|  |  |  |           selectors: [['my-comp']], | 
					
						
							|  |  |  |           factory: () => comp = new MyComp(directiveInject(ChangeDetectorRef as any)), | 
					
						
							|  |  |  |           consts: 1, | 
					
						
							|  |  |  |           vars: 0, | 
					
						
							|  |  |  |           template: function(rf: RenderFlags, ctx: MyComp) { | 
					
						
							|  |  |  |             if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |               projectionDef(); | 
					
						
							|  |  |  |               projection(0); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       class Directive { | 
					
						
							|  |  |  |         value: string; | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: Directive, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'dir', '']], | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           factory: () => dir = new Directive(directiveInject(ChangeDetectorRef as any)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['dir'] | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class DirectiveSameInstance { | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-08 21:57:50 -08:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |           type: DirectiveSameInstance, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'dirSame', '']], | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           factory: () => dirSameInstance = | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |                        new DirectiveSameInstance(directiveInject(ChangeDetectorRef as any)) | 
					
						
							| 
									
										
										
										
											2018-01-08 21:57:50 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |       const directives = [MyComp, Directive, DirectiveSameInstance, NgIf]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should inject current component ChangeDetectorRef into directives on the same node as components', | 
					
						
							|  |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |            /** <my-comp dir dirSame #dir="dir"></my-comp> {{ dir.value }} */ | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |            const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |              if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']); | 
					
						
							|  |  |  |                text(2); | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |              if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                const tmp = reference(1) as any; | 
					
						
							|  |  |  |                textBinding(2, bind(tmp.value)); | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |            }, 3, 1, directives); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const app = renderComponent(MyApp); | 
					
						
							|  |  |  |            // ChangeDetectorRef is the token, ViewRef has historically been the constructor
 | 
					
						
							|  |  |  |            expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef'); | 
					
						
							|  |  |  |            expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // Each ChangeDetectorRef instance should be unique
 | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(comp !.cdr); | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should inject host component ChangeDetectorRef into directives on normal elements', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            class MyApp { | 
					
						
							|  |  |  |              constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |                type: MyApp, | 
					
						
							|  |  |  |                selectors: [['my-app']], | 
					
						
							|  |  |  |                consts: 3, | 
					
						
							|  |  |  |                vars: 1, | 
					
						
							|  |  |  |                factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |                /** <div dir dirSame #dir="dir"> {{ dir.value }} </div> */ | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |                template: function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |                  if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                    elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); | 
					
						
							|  |  |  |                    { text(2); } | 
					
						
							|  |  |  |                    elementEnd(); | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  |                  if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                    const tmp = reference(1) as any; | 
					
						
							|  |  |  |                    textBinding(2, bind(tmp.value)); | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  |                }, | 
					
						
							|  |  |  |                directives: directives | 
					
						
							|  |  |  |              }); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:48:06 -07:00
										 |  |  |            } | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |            const app = renderComponent(MyApp); | 
					
						
							|  |  |  |            expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>'); | 
					
						
							|  |  |  |            expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // Each ChangeDetectorRef instance should be unique
 | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(app.cdr); | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); | 
					
						
							|  |  |  |          }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should inject host component ChangeDetectorRef into directives in a component\'s ContentChildren', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            class MyApp { | 
					
						
							|  |  |  |              constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |                type: MyApp, | 
					
						
							|  |  |  |                selectors: [['my-app']], | 
					
						
							|  |  |  |                consts: 4, | 
					
						
							|  |  |  |                vars: 1, | 
					
						
							|  |  |  |                factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), | 
					
						
							|  |  |  |                /** | 
					
						
							|  |  |  |                 * <my-comp> | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |                 *   <div dir dirSame #dir="dir"></div> | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |                 * </my-comp> | 
					
						
							|  |  |  |                 * {{ dir.value }} | 
					
						
							|  |  |  |                 */ | 
					
						
							|  |  |  |                template: function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |                  if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                    elementStart(0, 'my-comp'); | 
					
						
							|  |  |  |                    { element(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); } | 
					
						
							|  |  |  |                    elementEnd(); | 
					
						
							|  |  |  |                    text(3); | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  |                  if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                    const tmp = reference(2) as any; | 
					
						
							|  |  |  |                    textBinding(3, bind(tmp.value)); | 
					
						
							|  |  |  |                  } | 
					
						
							|  |  |  |                }, | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |                directives: directives | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |              }); | 
					
						
							|  |  |  |            } | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |            const app = renderComponent(MyApp); | 
					
						
							|  |  |  |            expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef'); | 
					
						
							|  |  |  |            expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |            // Each ChangeDetectorRef instance should be unique
 | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(app !.cdr); | 
					
						
							|  |  |  |            expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |       it('should inject host component ChangeDetectorRef into directives in embedded views', () => { | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         class MyApp { | 
					
						
							|  |  |  |           showing = true; | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |           static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |             type: MyApp, | 
					
						
							|  |  |  |             selectors: [['my-app']], | 
					
						
							|  |  |  |             factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), | 
					
						
							|  |  |  |             consts: 1, | 
					
						
							|  |  |  |             vars: 0, | 
					
						
							|  |  |  |             /** | 
					
						
							|  |  |  |              * % if (showing) { | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |            *   <div dir dirSame #dir="dir"> {{ dir.value }} </div> | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  |            * % } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |              */ | 
					
						
							|  |  |  |             template: function(rf: RenderFlags, ctx: MyApp) { | 
					
						
							|  |  |  |               if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |                 container(0); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                 containerRefreshStart(0); | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   if (ctx.showing) { | 
					
						
							|  |  |  |                     let rf1 = embeddedViewStart(0, 3, 1); | 
					
						
							|  |  |  |                     if (rf1 & RenderFlags.Create) { | 
					
						
							|  |  |  |                       elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); | 
					
						
							|  |  |  |                       { text(2); } | 
					
						
							|  |  |  |                       elementEnd(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (rf1 & RenderFlags.Update) { | 
					
						
							|  |  |  |                       const tmp = reference(1) as any; | 
					
						
							|  |  |  |                       textBinding(2, bind(tmp.value)); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |                   embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |                 containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |             }, | 
					
						
							|  |  |  |             directives: directives | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         const app = renderComponent(MyApp); | 
					
						
							|  |  |  |         expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>'); | 
					
						
							|  |  |  |         expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         // Each ChangeDetectorRef instance should be unique
 | 
					
						
							|  |  |  |         expect(dir !.cdr).not.toBe(app.cdr); | 
					
						
							|  |  |  |         expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |       it('should inject host component ChangeDetectorRef into directives on containers', () => { | 
					
						
							|  |  |  |         function C1(rf1: RenderFlags, ctx1: any) { | 
					
						
							|  |  |  |           if (rf1 & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); | 
					
						
							|  |  |  |             { text(2); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf1 & RenderFlags.Update) { | 
					
						
							|  |  |  |             const tmp = reference(1) as any; | 
					
						
							|  |  |  |             textBinding(2, bind(tmp.value)); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         class MyApp { | 
					
						
							|  |  |  |           showing = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           constructor(public cdr: ChangeDetectorRef) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |             type: MyApp, | 
					
						
							|  |  |  |             selectors: [['my-app']], | 
					
						
							|  |  |  |             factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), | 
					
						
							|  |  |  |             consts: 1, | 
					
						
							|  |  |  |             vars: 0, | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |             /** <div *ngIf="showing" dir dirSame #dir="dir"> {{ dir.value }} </div> */ | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |             template: function(rf: RenderFlags, ctx: MyApp) { | 
					
						
							|  |  |  |               if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |                 template( | 
					
						
							|  |  |  |                     0, C1, 3, 1, 'div', | 
					
						
							|  |  |  |                     ['dir', '', 'dirSame', '', AttributeMarker.Template, 'ngIf']); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |                 elementProperty(0, 'ngIf', bind(ctx.showing)); | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |               } | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             directives: directives | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         const app = renderComponent(MyApp); | 
					
						
							|  |  |  |         expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>'); | 
					
						
							|  |  |  |         expect((app !.cdr as ViewRef<MyApp>).context).toBe(app); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 18:38:13 -07:00
										 |  |  |         // Each ChangeDetectorRef instance should be unique
 | 
					
						
							|  |  |  |         expect(dir !.cdr).not.toBe(app.cdr); | 
					
						
							|  |  |  |         expect(dir !.cdr).not.toBe(dirSameInstance !.cdr); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-04-04 21:21:12 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-28 12:51:00 -08:00
										 |  |  |   describe('string tokens', () => { | 
					
						
							|  |  |  |     it('should be able to provide a string token', () => { | 
					
						
							|  |  |  |       let injectorDir !: InjectorDir; | 
					
						
							|  |  |  |       let divElement !: HTMLElement; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class InjectorDir { | 
					
						
							|  |  |  |         constructor(public value: string) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |           type: InjectorDir, | 
					
						
							|  |  |  |           selectors: [['', 'injectorDir', '']], | 
					
						
							|  |  |  |           factory: () => injectorDir = new InjectorDir(directiveInject('test' as any)), | 
					
						
							|  |  |  |           features: [ProvidersFeature([{provide: 'test', useValue: 'provided'}])], | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /** <div injectorDir otherInjectorDir></div> */ | 
					
						
							|  |  |  |       const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           element(0, 'div', ['injectorDir', '']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // testing only
 | 
					
						
							|  |  |  |         divElement = load(0); | 
					
						
							|  |  |  |       }, 1, 0, [InjectorDir]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |       expect(injectorDir.value).toBe('provided'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-16 17:43:29 +02:00
										 |  |  |   describe('Renderer2', () => { | 
					
						
							|  |  |  |     class MyComp { | 
					
						
							|  |  |  |       constructor(public renderer: Renderer2) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |         type: MyComp, | 
					
						
							|  |  |  |         selectors: [['my-comp']], | 
					
						
							| 
									
										
										
										
											2018-10-10 15:53:14 +02:00
										 |  |  |         factory: () => new MyComp(directiveInject(Renderer2 as any)), | 
					
						
							| 
									
										
										
										
											2018-08-16 17:43:29 +02:00
										 |  |  |         consts: 1, | 
					
						
							|  |  |  |         vars: 0, | 
					
						
							|  |  |  |         template: function(rf: RenderFlags, ctx: MyComp) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             text(0, 'Foo'); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should inject the Renderer2 used by the application', () => { | 
					
						
							|  |  |  |       const rendererFactory = getRendererFactory2(document); | 
					
						
							| 
									
										
										
										
											2018-10-10 15:53:14 +02:00
										 |  |  |       const fixture = new ComponentFixture(MyComp, {rendererFactory: rendererFactory}); | 
					
						
							|  |  |  |       expect(isProceduralRenderer(fixture.component.renderer)).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2018-08-16 17:43:29 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw when injecting Renderer2 but the application is using Renderer3', | 
					
						
							|  |  |  |        () => { expect(() => new ComponentFixture(MyComp)).toThrow(); }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |   describe('@Attribute', () => { | 
					
						
							| 
									
										
										
										
											2018-10-08 16:04:46 -07:00
										 |  |  |     let myDirectiveInstance !: MyDirective | null; | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |     class MyDirective { | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       exists = 'wrong' as string | null; | 
					
						
							|  |  |  |       myDirective = 'wrong' as string | null; | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |       constructor( | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |           @Attribute('exist') existAttrValue: string|null, | 
					
						
							|  |  |  |           @Attribute('myDirective') myDirectiveAttrValue: string|null) { | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |         this.exists = existAttrValue; | 
					
						
							|  |  |  |         this.myDirective = myDirectiveAttrValue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       static ngDirectiveDef = defineDirective({ | 
					
						
							|  |  |  |         type: MyDirective, | 
					
						
							|  |  |  |         selectors: [['', 'myDirective', '']], | 
					
						
							| 
									
										
										
										
											2018-10-08 16:04:46 -07:00
										 |  |  |         factory: () => myDirectiveInstance = | 
					
						
							|  |  |  |                      new MyDirective(injectAttribute('exist'), injectAttribute('myDirective')) | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 16:04:46 -07:00
										 |  |  |     beforeEach(() => myDirectiveInstance = null); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |     it('should inject attribute', () => { | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       let exist = 'wrong' as string | null; | 
					
						
							|  |  |  |       let nonExist = 'wrong' as string | null; | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           elementStart(0, 'div', ['exist', 'existValue', 'other', 'ignore']); | 
					
						
							|  |  |  |           exist = injectAttribute('exist'); | 
					
						
							|  |  |  |           nonExist = injectAttribute('nonExist'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-21 00:03:21 -07:00
										 |  |  |       }, 1); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(MyApp); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |       expect(exist).toEqual('existValue'); | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       expect(nonExist).toBeNull(); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |     // https://stackblitz.com/edit/angular-scawyi?file=src%2Fapp%2Fapp.component.ts
 | 
					
						
							|  |  |  |     it('should inject attributes on <ng-template>', () => { | 
					
						
							|  |  |  |       let myDirectiveInstance: MyDirective; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* <ng-template myDirective="initial" exist="existValue" other="ignore"></ng-template>*/ | 
					
						
							|  |  |  |       const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           template( | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |               0, null, 0, 0, 'ng-template', | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |               ['myDirective', 'initial', 'exist', 'existValue', 'other', 'ignore']); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							| 
									
										
										
										
											2018-10-05 21:23:41 -07:00
										 |  |  |           myDirectiveInstance = getDirectiveOnNode(0); | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, 1, 0, [MyDirective]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       new ComponentFixture(MyApp); | 
					
						
							|  |  |  |       expect(myDirectiveInstance !.exists).toEqual('existValue'); | 
					
						
							|  |  |  |       expect(myDirectiveInstance !.myDirective).toEqual('initial'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // https://stackblitz.com/edit/angular-scawyi?file=src%2Fapp%2Fapp.component.ts
 | 
					
						
							|  |  |  |     it('should inject attributes on <ng-container>', () => { | 
					
						
							|  |  |  |       let myDirectiveInstance: MyDirective; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* <ng-container myDirective="initial" exist="existValue" other="ignore"></ng-container>*/ | 
					
						
							|  |  |  |       const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           elementContainerStart( | 
					
						
							|  |  |  |               0, ['myDirective', 'initial', 'exist', 'existValue', 'other', 'ignore']); | 
					
						
							|  |  |  |           elementContainerEnd(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							| 
									
										
										
										
											2018-10-05 21:23:41 -07:00
										 |  |  |           myDirectiveInstance = getDirectiveOnNode(0); | 
					
						
							| 
									
										
										
										
											2018-08-28 14:13:32 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, 1, 0, [MyDirective]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       new ComponentFixture(MyApp); | 
					
						
							|  |  |  |       expect(myDirectiveInstance !.exists).toEqual('existValue'); | 
					
						
							|  |  |  |       expect(myDirectiveInstance !.myDirective).toEqual('initial'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |     // https://stackblitz.com/edit/angular-8ytqkp?file=src%2Fapp%2Fapp.component.ts
 | 
					
						
							|  |  |  |     it('should not inject attributes representing bindings and outputs', () => { | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       let exist = 'wrong' as string | null; | 
					
						
							|  |  |  |       let nonExist = 'wrong' as string | null; | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |           elementStart(0, 'div', ['exist', 'existValue', AttributeMarker.Bindings, 'nonExist']); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |           exist = injectAttribute('exist'); | 
					
						
							|  |  |  |           nonExist = injectAttribute('nonExist'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       }, 1); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(MyApp); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |       expect(exist).toEqual('existValue'); | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       expect(nonExist).toBeNull(); | 
					
						
							| 
									
										
										
										
											2018-02-28 22:18:34 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |     it('should not accidentally inject attributes representing bindings and outputs', () => { | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       let exist = 'wrong' as string | null; | 
					
						
							|  |  |  |       let nonExist = 'wrong' as string | null; | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           elementStart(0, 'div', [ | 
					
						
							| 
									
										
										
										
											2019-03-07 08:31:31 +00:00
										 |  |  |             'exist', 'existValue', AttributeMarker.Bindings, 'binding1', 'nonExist', 'binding2' | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |           ]); | 
					
						
							|  |  |  |           exist = injectAttribute('exist'); | 
					
						
							|  |  |  |           nonExist = injectAttribute('nonExist'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       }, 1); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 09:56:35 -07:00
										 |  |  |       new ComponentFixture(MyApp); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |       expect(exist).toEqual('existValue'); | 
					
						
							| 
									
										
										
										
											2018-11-22 16:03:26 +01:00
										 |  |  |       expect(nonExist).toBeNull(); | 
					
						
							| 
									
										
										
										
											2018-05-04 15:58:42 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-02-26 16:58:15 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |   describe('inject', () => { | 
					
						
							|  |  |  |     describe('bloom filter', () => { | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |       let mockTView: any; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         mockTView = {data: [0, 0, 0, 0, 0, 0, 0, 0, null], firstTemplatePass: true}; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |       function bloomState() { return mockTView.data.slice(0, TNODE).reverse(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class Dir0 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir1 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir33 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 33; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir66 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 66; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir99 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 99; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir132 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 132; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir165 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 165; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir198 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 198; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       class Dir231 { | 
					
						
							|  |  |  |         /** @internal */ static __NG_ELEMENT_ID__ = 231; | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should add values', () => { | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir0); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 0, 0, 0, 0, 0, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir33); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 0, 0, 0, 0, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir66); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 0, 0, 0, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir99); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 0, 0, 8, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir132); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 0, 16, 8, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir165); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 0, 32, 16, 8, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir198); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([0, 64, 32, 16, 8, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir231); | 
					
						
							| 
									
										
										
										
											2018-03-14 13:29:48 -07:00
										 |  |  |         expect(bloomState()).toEqual([128, 64, 32, 16, 8, 4, 2, 1]); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should query values', () => { | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |         bloomAdd(0, mockTView, Dir0); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir33); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir66); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir99); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir132); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir165); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir198); | 
					
						
							|  |  |  |         bloomAdd(0, mockTView, Dir231); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         expect(bloomHasToken(bloomHash(Dir0) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir1) as number, 0, mockTView.data)).toEqual(false); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir33) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir66) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir99) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir132) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir165) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir198) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							|  |  |  |         expect(bloomHasToken(bloomHash(Dir231) as number, 0, mockTView.data)).toEqual(true); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should inject from parent view', () => { | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |       const ParentDirective = createDirective('parentDir'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       class ChildDirective { | 
					
						
							|  |  |  |         value: string; | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |         constructor(public parent: any) { this.value = (parent.constructor as any).name; } | 
					
						
							| 
									
										
										
										
											2018-01-08 21:57:50 -08:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |           type: ChildDirective, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'childDir', '']], | 
					
						
							| 
									
										
										
										
											2018-03-04 20:21:23 -08:00
										 |  |  |           factory: () => new ChildDirective(directiveInject(ParentDirective)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['childDir'] | 
					
						
							| 
									
										
										
										
											2018-01-08 21:57:50 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       class Child2Directive { | 
					
						
							|  |  |  |         value: boolean; | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |         constructor(parent: any, child: ChildDirective) { this.value = parent === child.parent; } | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         static ngDirectiveDef = defineDirective({ | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |           selectors: [['', 'child2Dir', '']], | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |           type: Child2Directive, | 
					
						
							| 
									
										
										
										
											2018-03-04 20:21:23 -08:00
										 |  |  |           factory: () => new Child2Directive( | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |                        directiveInject(ParentDirective), directiveInject(ChildDirective)), | 
					
						
							| 
									
										
										
										
											2019-01-10 22:24:32 +01:00
										 |  |  |           exportAs: ['child2Dir'] | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |       /** | 
					
						
							|  |  |  |        * <div parentDir> | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |        *    % if (...) { | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |        *    <span childDir child2Dir #child1="childDir" #child2="child2Dir"> | 
					
						
							|  |  |  |        *      {{ child1.value }} - {{ child2.value }} | 
					
						
							|  |  |  |        *    </span> | 
					
						
							| 
									
										
										
										
											2018-10-02 21:12:26 -07:00
										 |  |  |        *    % } | 
					
						
							| 
									
										
										
										
											2018-03-27 11:01:52 -07:00
										 |  |  |        * </div> | 
					
						
							|  |  |  |        */ | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |           elementStart(0, 'div', ['parentDir', '']); | 
					
						
							| 
									
										
										
										
											2018-03-21 15:10:34 -07:00
										 |  |  |           { container(1); } | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           containerRefreshStart(1); | 
					
						
							|  |  |  |           { | 
					
						
							| 
									
										
										
										
											2018-08-21 00:03:21 -07:00
										 |  |  |             let rf1 = embeddedViewStart(0, 4, 2); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |             if (rf1 & RenderFlags.Create) { | 
					
						
							|  |  |  |               elementStart( | 
					
						
							|  |  |  |                   0, 'span', ['childDir', '', 'child2Dir', ''], | 
					
						
							|  |  |  |                   ['child1', 'childDir', 'child2', 'child2Dir']); | 
					
						
							|  |  |  |               { text(3); } | 
					
						
							|  |  |  |               elementEnd(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf & RenderFlags.Update) { | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |               const tmp1 = reference(1) as any; | 
					
						
							|  |  |  |               const tmp2 = reference(2) as any; | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |               textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, '')); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       }, 2, 0, [ChildDirective, Child2Directive, ParentDirective]); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |       expect(fixture.html) | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  |           .toEqual('<div parentdir=""><span child2dir="" childdir="">Directive-true</span></div>'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should inject from module Injector', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                                              }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('getOrCreateNodeInjector', () => { | 
					
						
							|  |  |  |     it('should handle initial undefined state', () => { | 
					
						
							| 
									
										
										
										
											2018-11-21 21:14:06 -08:00
										 |  |  |       const contentView = createLView( | 
					
						
							| 
									
										
										
										
											2019-02-12 00:03:04 +01:00
										 |  |  |           null, createTView(-1, null, 1, 0, null, null, null, null), null, LViewFlags.CheckAlways, | 
					
						
							|  |  |  |           null, null, {} as any, {} as any); | 
					
						
							| 
									
										
										
										
											2018-09-05 16:15:37 -07:00
										 |  |  |       const oldView = enterView(contentView, null); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       try { | 
					
						
							| 
									
										
										
										
											2018-10-12 18:49:00 -07:00
										 |  |  |         const parentTNode = createNodeAtIndex(0, TNodeType.Element, null, null, null); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         // Simulate the situation where the previous parent is not initialized.
 | 
					
						
							|  |  |  |         // This happens on first bootstrap because we don't init existing values
 | 
					
						
							|  |  |  |         // so that we have smaller HelloWorld.
 | 
					
						
							| 
									
										
										
										
											2018-09-13 16:07:23 -07:00
										 |  |  |         (parentTNode as{parent: any}).parent = undefined; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  |         const injector = getOrCreateNodeInjectorForNode(parentTNode, contentView); | 
					
						
							| 
									
										
										
										
											2018-10-08 16:04:46 -07:00
										 |  |  |         expect(injector).not.toEqual(-1); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       } finally { | 
					
						
							|  |  |  |         leaveView(oldView); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }); |