| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 18:40:08 -08:00
										 |  |  | import {ViewEncapsulation, createInjector, defineInjectable, defineInjector} from '../../src/core'; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-15 08:43:56 -08:00
										 |  |  | import {AttributeMarker, ComponentFactory, LifecycleHooksFeature, defineComponent, directiveInject, markDirty, template, getRenderedText} from '../../src/render3/index'; | 
					
						
							| 
									
										
										
										
											2018-11-12 18:40:08 -08:00
										 |  |  | import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, nextContext, text, textBinding, tick} from '../../src/render3/instructions'; | 
					
						
							| 
									
										
										
										
											2018-10-18 09:23:18 +02:00
										 |  |  | import {ComponentDef, RenderFlags} from '../../src/render3/interfaces/definition'; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  | import {NgIf} from './common_with_def'; | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  | import {getRendererFactory2} from './imported_renderer2'; | 
					
						
							| 
									
										
										
										
											2018-12-10 23:40:19 -08:00
										 |  |  | import {ComponentFixture, MockRendererFactory, containerEl, createComponent, renderComponent, renderToHtml, requestAnimationFrame, toHtml} from './render_util'; | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('component', () => { | 
					
						
							|  |  |  |   class CounterComponent { | 
					
						
							|  |  |  |     count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     increment() { this.count++; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |       type: CounterComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['counter']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 1, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: function(rf: RenderFlags, ctx: CounterComponent) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           text(0); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           textBinding(0, bind(ctx.count)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       }, | 
					
						
							|  |  |  |       factory: () => new CounterComponent, | 
					
						
							|  |  |  |       inputs: {count: 'count'}, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('renderComponent', () => { | 
					
						
							|  |  |  |     it('should render on initial call', () => { | 
					
						
							|  |  |  |       renderComponent(CounterComponent); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('0'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should re-render on input change or method invocation', () => { | 
					
						
							|  |  |  |       const component = renderComponent(CounterComponent); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('0'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       component.count = 123; | 
					
						
							| 
									
										
										
										
											2018-02-03 20:34:30 -08:00
										 |  |  |       markDirty(component); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('0'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       requestAnimationFrame.flush(); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('123'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       component.increment(); | 
					
						
							| 
									
										
										
										
											2018-02-03 20:34:30 -08:00
										 |  |  |       markDirty(component); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('123'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |       requestAnimationFrame.flush(); | 
					
						
							| 
									
										
										
										
											2018-01-03 11:42:48 +01:00
										 |  |  |       expect(toHtml(containerEl)).toEqual('124'); | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 15:54:16 -07:00
										 |  |  |     class MyService { | 
					
						
							|  |  |  |       constructor(public value: string) {} | 
					
						
							|  |  |  |       static ngInjectableDef = | 
					
						
							|  |  |  |           defineInjectable({providedIn: 'root', factory: () => new MyService('no-injector')}); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     class MyComponent { | 
					
						
							|  |  |  |       constructor(public myService: MyService) {} | 
					
						
							|  |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |         type: MyComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |         encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-04-12 15:54:16 -07:00
										 |  |  |         selectors: [['my-component']], | 
					
						
							|  |  |  |         factory: () => new MyComponent(directiveInject(MyService)), | 
					
						
							| 
									
										
										
										
											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
										 |  |  |         template: function(fs: RenderFlags, ctx: MyComponent) { | 
					
						
							|  |  |  |           if (fs & RenderFlags.Create) { | 
					
						
							|  |  |  |             text(0); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (fs & RenderFlags.Update) { | 
					
						
							|  |  |  |             textBinding(0, bind(ctx.myService.value)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class MyModule { | 
					
						
							|  |  |  |       static ngInjectorDef = defineInjector({ | 
					
						
							|  |  |  |         factory: () => new MyModule(), | 
					
						
							|  |  |  |         providers: [{provide: MyService, useValue: new MyService('injector')}] | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should support bootstrapping without injector', () => { | 
					
						
							|  |  |  |       const fixture = new ComponentFixture(MyComponent); | 
					
						
							|  |  |  |       expect(fixture.html).toEqual('no-injector'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should support bootstrapping with injector', () => { | 
					
						
							|  |  |  |       const fixture = new ComponentFixture(MyComponent, {injector: createInjector(MyModule)}); | 
					
						
							|  |  |  |       expect(fixture.html).toEqual('injector'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-26 14:57:45 -08:00
										 |  |  |   it('should instantiate components at high indices', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // {{ name }}
 | 
					
						
							|  |  |  |     class Comp { | 
					
						
							|  |  |  |       // @Input
 | 
					
						
							|  |  |  |       name = ''; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |         type: Comp, | 
					
						
							|  |  |  |         selectors: [['comp']], | 
					
						
							|  |  |  |         factory: () => new Comp(), | 
					
						
							|  |  |  |         consts: 1, | 
					
						
							|  |  |  |         vars: 1, | 
					
						
							|  |  |  |         template: (rf: RenderFlags, ctx: Comp) => { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |             text(0); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |             textBinding(0, bind(ctx.name)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         inputs: {name: 'name'} | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Artificially inflating the slot IDs of this app component to mimic an app
 | 
					
						
							|  |  |  |     // with a very large view
 | 
					
						
							|  |  |  |     const App = createComponent('app', (rf: RenderFlags, ctx: any) => { | 
					
						
							|  |  |  |       if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |         element(4097, 'comp'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |         elementProperty(4097, 'name', bind(ctx.name)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, 4098, 1, [Comp]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |     expect(fixture.html).toEqual('<comp></comp>'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fixture.component.name = 'some name'; | 
					
						
							|  |  |  |     fixture.update(); | 
					
						
							|  |  |  |     expect(fixture.html).toEqual('<comp>some name</comp>'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 14:23:03 -08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 23:40:19 -08:00
										 |  |  | it('should not invoke renderer destroy method for embedded views', () => { | 
					
						
							|  |  |  |   let comp: Comp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function MyComponent_div_Template_2(rf: any, ctx: any) { | 
					
						
							|  |  |  |     if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |       elementStart(0, 'div'); | 
					
						
							|  |  |  |       text(1, 'Child view'); | 
					
						
							|  |  |  |       elementEnd(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class Comp { | 
					
						
							|  |  |  |     visible = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |       type: Comp, | 
					
						
							|  |  |  |       selectors: [['comp']], | 
					
						
							|  |  |  |       consts: 3, | 
					
						
							|  |  |  |       vars: 1, | 
					
						
							|  |  |  |       factory: () => { | 
					
						
							|  |  |  |         comp = new Comp(); | 
					
						
							|  |  |  |         return comp; | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       directives: [NgIf], | 
					
						
							|  |  |  |       /** | 
					
						
							|  |  |  |        *  <div>Root view</div> | 
					
						
							|  |  |  |        *  <div *ngIf="visible">Child view</div> | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       template: function(rf: RenderFlags, ctx: Comp) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           elementStart(0, 'div'); | 
					
						
							|  |  |  |           text(1, 'Root view'); | 
					
						
							|  |  |  |           elementEnd(); | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |           template(2, MyComponent_div_Template_2, 2, 0, null, [AttributeMarker.SelectOnly, 'ngIf']); | 
					
						
							| 
									
										
										
										
											2018-12-10 23:40:19 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           elementProperty(2, 'ngIf', bind(ctx.visible)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const rendererFactory = new MockRendererFactory(['destroy']); | 
					
						
							|  |  |  |   const fixture = new ComponentFixture(Comp, {rendererFactory}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   comp !.visible = false; | 
					
						
							|  |  |  |   fixture.update(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   comp !.visible = true; | 
					
						
							|  |  |  |   fixture.update(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const renderer = rendererFactory.lastRenderer !; | 
					
						
							|  |  |  |   const destroySpy = renderer.spies['destroy']; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // we should never see `destroy` method being called
 | 
					
						
							|  |  |  |   // in case child views are created/removed
 | 
					
						
							|  |  |  |   expect(destroySpy.calls.count()).toBe(0); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  | describe('component with a container', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |   function showItems(rf: RenderFlags, ctx: {items: string[]}) { | 
					
						
							|  |  |  |     if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |       container(0); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |     if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |       containerRefreshStart(0); | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         for (const item of ctx.items) { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           const rf0 = embeddedViewStart(0, 1, 1); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           { | 
					
						
							|  |  |  |             if (rf0 & RenderFlags.Create) { | 
					
						
							|  |  |  |               text(0); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (rf0 & RenderFlags.Update) { | 
					
						
							|  |  |  |               textBinding(0, bind(item)); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class WrapperComponent { | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |     // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |     items !: string[]; | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |       type: WrapperComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['wrapper']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: function ChildComponentTemplate(rf: RenderFlags, ctx: {items: string[]}) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           container(0); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           containerRefreshStart(0); | 
					
						
							|  |  |  |           { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |             const rf0 = embeddedViewStart(0, 1, 0); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |             { showItems(rf0, {items: ctx.items}); } | 
					
						
							|  |  |  |             embeddedViewEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       factory: () => new WrapperComponent, | 
					
						
							|  |  |  |       inputs: {items: 'items'} | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |   function template(rf: RenderFlags, ctx: {items: string[]}) { | 
					
						
							|  |  |  |     if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |       element(0, 'wrapper'); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |     if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |       elementProperty(0, 'items', bind(ctx.items)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 12:58:41 -07:00
										 |  |  |   const defs = [WrapperComponent]; | 
					
						
							| 
									
										
										
										
											2018-03-25 21:32:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |   it('should re-render on input change', () => { | 
					
						
							|  |  |  |     const ctx: {items: string[]} = {items: ['a']}; | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |     expect(renderToHtml(template, ctx, 1, 1, defs)).toEqual('<wrapper>a</wrapper>'); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ctx.items = [...ctx.items, 'b']; | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |     expect(renderToHtml(template, ctx, 1, 1, defs)).toEqual('<wrapper>ab</wrapper>'); | 
					
						
							| 
									
										
										
										
											2018-01-25 15:32:21 +01:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  | // TODO: add tests with Native once tests are run in real browser (domino doesn't support shadow
 | 
					
						
							|  |  |  | // root)
 | 
					
						
							|  |  |  | describe('encapsulation', () => { | 
					
						
							|  |  |  |   class WrapperComponent { | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |       type: WrapperComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['wrapper']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: function(rf: RenderFlags, ctx: WrapperComponent) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |           element(0, 'encapsulated'); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       factory: () => new WrapperComponent, | 
					
						
							| 
									
										
										
										
											2018-03-29 12:58:41 -07:00
										 |  |  |       directives: () => [EncapsulatedComponent] | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class EncapsulatedComponent { | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |       type: EncapsulatedComponent, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['encapsulated']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 2, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: function(rf: RenderFlags, ctx: EncapsulatedComponent) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           text(0, 'foo'); | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |           element(1, 'leaf'); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       factory: () => new EncapsulatedComponent, | 
					
						
							| 
									
										
										
										
											2018-08-08 13:22:52 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.Emulated, | 
					
						
							|  |  |  |       styles: [], | 
					
						
							|  |  |  |       data: {}, | 
					
						
							| 
									
										
										
										
											2018-03-29 12:58:41 -07:00
										 |  |  |       directives: () => [LeafComponent] | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class LeafComponent { | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |       type: LeafComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['leaf']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 2, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: function(rf: RenderFlags, ctx: LeafComponent) { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |           elementStart(0, 'span'); | 
					
						
							|  |  |  |           { text(1, 'bar'); } | 
					
						
							|  |  |  |           elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       factory: () => new LeafComponent, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should encapsulate children, but not host nor grand children', () => { | 
					
						
							| 
									
										
										
										
											2018-03-06 10:13:49 -08:00
										 |  |  |     renderComponent(WrapperComponent, {rendererFactory: getRendererFactory2(document)}); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |     expect(containerEl.outerHTML) | 
					
						
							| 
									
										
										
										
											2018-01-03 10:45:09 +01:00
										 |  |  |         .toMatch( | 
					
						
							|  |  |  |             /<div host=""><encapsulated _nghost-c(\d+)="">foo<leaf _ngcontent-c\1=""><span>bar<\/span><\/leaf><\/encapsulated><\/div>/); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should encapsulate host', () => { | 
					
						
							| 
									
										
										
										
											2018-03-06 10:13:49 -08:00
										 |  |  |     renderComponent(EncapsulatedComponent, {rendererFactory: getRendererFactory2(document)}); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |     expect(containerEl.outerHTML) | 
					
						
							| 
									
										
										
										
											2018-01-03 10:45:09 +01:00
										 |  |  |         .toMatch( | 
					
						
							|  |  |  |             /<div host="" _nghost-c(\d+)="">foo<leaf _ngcontent-c\1=""><span>bar<\/span><\/leaf><\/div>/); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should encapsulate host and children with different attributes', () => { | 
					
						
							|  |  |  |     class WrapperComponentWith { | 
					
						
							|  |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         type: WrapperComponentWith, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |         selectors: [['wrapper']], | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |         consts: 1, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         template: function(rf: RenderFlags, ctx: WrapperComponentWith) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |             element(0, 'leaf'); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         factory: () => new WrapperComponentWith, | 
					
						
							| 
									
										
										
										
											2018-08-08 13:22:52 -07:00
										 |  |  |         encapsulation: ViewEncapsulation.Emulated, | 
					
						
							|  |  |  |         styles: [], | 
					
						
							|  |  |  |         data: {}, | 
					
						
							| 
									
										
										
										
											2018-03-29 12:58:41 -07:00
										 |  |  |         directives: () => [LeafComponentwith] | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class LeafComponentwith { | 
					
						
							|  |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							| 
									
										
										
										
											2018-01-22 15:27:21 -08:00
										 |  |  |         type: LeafComponentwith, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |         selectors: [['leaf']], | 
					
						
							| 
									
										
										
										
											2018-08-21 00:03:21 -07:00
										 |  |  |         consts: 2, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         vars: 0, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         template: function(rf: RenderFlags, ctx: LeafComponentwith) { | 
					
						
							|  |  |  |           if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-02-06 16:11:20 -08:00
										 |  |  |             elementStart(0, 'span'); | 
					
						
							|  |  |  |             { text(1, 'bar'); } | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         factory: () => new LeafComponentwith, | 
					
						
							| 
									
										
										
										
											2018-08-08 13:22:52 -07:00
										 |  |  |         encapsulation: ViewEncapsulation.Emulated, | 
					
						
							|  |  |  |         styles: [], | 
					
						
							|  |  |  |         data: {}, | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 10:13:49 -08:00
										 |  |  |     renderComponent(WrapperComponentWith, {rendererFactory: getRendererFactory2(document)}); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |     expect(containerEl.outerHTML) | 
					
						
							| 
									
										
										
										
											2018-01-03 10:45:09 +01:00
										 |  |  |         .toMatch( | 
					
						
							|  |  |  |             /<div host="" _nghost-c(\d+)=""><leaf _ngcontent-c\1="" _nghost-c(\d+)=""><span _ngcontent-c\2="">bar<\/span><\/leaf><\/div>/); | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-02-03 20:34:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-11 16:30:46 +01:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | describe('recursive components', () => { | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |   let events: string[]; | 
					
						
							|  |  |  |   let count: number; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     events = []; | 
					
						
							|  |  |  |     count = 0; | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   class TreeNode { | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         public value: number, public depth: number, public left: TreeNode|null, | 
					
						
							|  |  |  |         public right: TreeNode|null) {} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * {{ data.value }} | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * % if (data.left != null) { | 
					
						
							|  |  |  |    *   <tree-comp [data]="data.left"></tree-comp> | 
					
						
							|  |  |  |    * % } | 
					
						
							|  |  |  |    * % if (data.right != null) { | 
					
						
							|  |  |  |    *   <tree-comp [data]="data.right"></tree-comp> | 
					
						
							|  |  |  |    * % } | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |   class TreeComponent { | 
					
						
							|  |  |  |     data: TreeNode = _buildTree(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ngDoCheck() { events.push('check' + this.data.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |     ngOnDestroy() { events.push('destroy' + this.data.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |       type: TreeComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-29 16:41:45 -07:00
										 |  |  |       selectors: [['tree-comp']], | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |       factory: () => new TreeComponent(), | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 3, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 1, | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |       template: (rf: RenderFlags, ctx: TreeComponent) => { | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |           text(0); | 
					
						
							|  |  |  |           container(1); | 
					
						
							|  |  |  |           container(2); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           textBinding(0, bind(ctx.data.value)); | 
					
						
							|  |  |  |           containerRefreshStart(1); | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             if (ctx.data.left != null) { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |               let rf0 = embeddedViewStart(0, 1, 1); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |               if (rf0 & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |                 element(0, 'tree-comp'); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |               } | 
					
						
							|  |  |  |               if (rf0 & RenderFlags.Update) { | 
					
						
							|  |  |  |                 elementProperty(0, 'data', bind(ctx.data.left)); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           containerRefreshEnd(); | 
					
						
							|  |  |  |           containerRefreshStart(2); | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             if (ctx.data.right != null) { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |               let rf0 = embeddedViewStart(0, 1, 1); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |               if (rf0 & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-27 14:28:22 -07:00
										 |  |  |                 element(0, 'tree-comp'); | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |               } | 
					
						
							|  |  |  |               if (rf0 & RenderFlags.Update) { | 
					
						
							|  |  |  |                 elementProperty(0, 'data', bind(ctx.data.right)); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               embeddedViewEnd(); | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:09 -07:00
										 |  |  |           containerRefreshEnd(); | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       inputs: {data: 'data'} | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 12:12:06 -07:00
										 |  |  |   (TreeComponent.ngComponentDef as ComponentDef<TreeComponent>).directiveDefs = | 
					
						
							| 
									
										
										
										
											2018-04-14 09:18:38 -07:00
										 |  |  |       () => [TreeComponent.ngComponentDef]; | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * {{ data.value }} | 
					
						
							|  |  |  |    *  <ng-if-tree [data]="data.left" *ngIf="data.left"></ng-if-tree> | 
					
						
							|  |  |  |    *  <ng-if-tree [data]="data.right" *ngIf="data.right"></ng-if-tree> | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   class NgIfTree { | 
					
						
							|  |  |  |     data: TreeNode = _buildTree(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-18 16:58:51 -08:00
										 |  |  |     ngDoCheck() { events.push('check' + this.data.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |     ngOnDestroy() { events.push('destroy' + this.data.value); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |       type: NgIfTree, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |       encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |       selectors: [['ng-if-tree']], | 
					
						
							|  |  |  |       factory: () => new NgIfTree(), | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |       consts: 3, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |       vars: 3, | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |       template: (rf: RenderFlags, ctx: NgIfTree) => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |           text(0); | 
					
						
							| 
									
										
										
										
											2018-12-12 15:23:12 -08:00
										 |  |  |           template(1, IfTemplate, 1, 1, 'ng-if-tree', [AttributeMarker.SelectOnly, 'ngIf']); | 
					
						
							|  |  |  |           template(2, IfTemplate2, 1, 1, 'ng-if-tree', [AttributeMarker.SelectOnly, 'ngIf']); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |           textBinding(0, bind(ctx.data.value)); | 
					
						
							|  |  |  |           elementProperty(1, 'ngIf', bind(ctx.data.left)); | 
					
						
							|  |  |  |           elementProperty(2, 'ngIf', bind(ctx.data.right)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       inputs: {data: 'data'}, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-07-18 01:59:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |   function IfTemplate(rf: RenderFlags, left: any) { | 
					
						
							|  |  |  |     if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-18 01:59:49 +00:00
										 |  |  |       elementStart(0, 'ng-if-tree'); | 
					
						
							|  |  |  |       elementEnd(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |     if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |       const parent = nextContext(); | 
					
						
							| 
									
										
										
										
											2018-07-18 01:59:49 +00:00
										 |  |  |       elementProperty(0, 'data', bind(parent.data.left)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |   function IfTemplate2(rf: RenderFlags, right: any) { | 
					
						
							|  |  |  |     if (rf & RenderFlags.Create) { | 
					
						
							| 
									
										
										
										
											2018-07-18 01:59:49 +00:00
										 |  |  |       elementStart(0, 'ng-if-tree'); | 
					
						
							|  |  |  |       elementEnd(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-25 17:25:22 -07:00
										 |  |  |     if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |       const parent = nextContext(); | 
					
						
							| 
									
										
										
										
											2018-07-18 01:59:49 +00:00
										 |  |  |       elementProperty(0, 'data', bind(parent.data.right)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 12:12:06 -07:00
										 |  |  |   (NgIfTree.ngComponentDef as ComponentDef<NgIfTree>).directiveDefs = | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |       () => [NgIfTree.ngComponentDef, NgIf.ngDirectiveDef]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  |   function _buildTree(currDepth: number): TreeNode { | 
					
						
							|  |  |  |     const children = currDepth < 2 ? _buildTree(currDepth + 1) : null; | 
					
						
							|  |  |  |     const children2 = currDepth < 2 ? _buildTree(currDepth + 1) : null; | 
					
						
							|  |  |  |     return new TreeNode(count++, currDepth, children, children2); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should check each component just once', () => { | 
					
						
							|  |  |  |     const comp = renderComponent(TreeComponent, {hostFeatures: [LifecycleHooksFeature]}); | 
					
						
							|  |  |  |     expect(getRenderedText(comp)).toEqual('6201534'); | 
					
						
							|  |  |  |     expect(events).toEqual(['check6', 'check2', 'check0', 'check1', 'check5', 'check3', 'check4']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     events = []; | 
					
						
							|  |  |  |     tick(comp); | 
					
						
							|  |  |  |     expect(events).toEqual(['check6', 'check2', 'check0', 'check1', 'check5', 'check3', 'check4']); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-05-09 16:49:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |   // This tests that the view tree is set up properly for recursive components
 | 
					
						
							|  |  |  |   it('should call onDestroys properly', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * % if (!skipContent) { | 
					
						
							|  |  |  |      *   <tree-comp></tree-comp> | 
					
						
							|  |  |  |      * % } | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |       if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |         container(0); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |         containerRefreshStart(0); | 
					
						
							|  |  |  |         if (!ctx.skipContent) { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           const rf0 = embeddedViewStart(0, 1, 0); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |           if (rf0 & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'tree-comp'); | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           embeddedViewEnd(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         containerRefreshEnd(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |     }, 1, 0, [TreeComponent]); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |     expect(getRenderedText(fixture.component)).toEqual('6201534'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     events = []; | 
					
						
							|  |  |  |     fixture.component.skipContent = true; | 
					
						
							|  |  |  |     fixture.update(); | 
					
						
							|  |  |  |     expect(events).toEqual( | 
					
						
							|  |  |  |         ['destroy0', 'destroy1', 'destroy2', 'destroy3', 'destroy4', 'destroy5', 'destroy6']); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should call onDestroys properly with ngIf', () => { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * % if (!skipContent) { | 
					
						
							|  |  |  |      *   <ng-if-tree></ng-if-tree> | 
					
						
							|  |  |  |      * % } | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | 
					
						
							|  |  |  |       if (rf & RenderFlags.Create) { | 
					
						
							|  |  |  |         container(0); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (rf & RenderFlags.Update) { | 
					
						
							|  |  |  |         containerRefreshStart(0); | 
					
						
							|  |  |  |         if (!ctx.skipContent) { | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |           const rf0 = embeddedViewStart(0, 1, 0); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  |           if (rf0 & RenderFlags.Create) { | 
					
						
							|  |  |  |             elementStart(0, 'ng-if-tree'); | 
					
						
							|  |  |  |             elementEnd(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           embeddedViewEnd(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         containerRefreshEnd(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |     }, 1, 0, [NgIfTree]); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const fixture = new ComponentFixture(App); | 
					
						
							|  |  |  |     expect(getRenderedText(fixture.component)).toEqual('6201534'); | 
					
						
							| 
									
										
										
										
											2018-12-18 16:58:51 -08:00
										 |  |  |     expect(events).toEqual(['check6', 'check2', 'check0', 'check1', 'check5', 'check3', 'check4']); | 
					
						
							| 
									
										
										
										
											2018-07-17 11:45:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     events = []; | 
					
						
							|  |  |  |     fixture.component.skipContent = true; | 
					
						
							|  |  |  |     fixture.update(); | 
					
						
							|  |  |  |     expect(events).toEqual( | 
					
						
							|  |  |  |         ['destroy0', 'destroy1', 'destroy2', 'destroy3', 'destroy4', 'destroy5', 'destroy6']); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 16:49:39 -07:00
										 |  |  |   it('should map inputs minified & unminified names', async() => { | 
					
						
							|  |  |  |     class TestInputsComponent { | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |       // TODO(issue/24571): remove '!'.
 | 
					
						
							|  |  |  |       minifiedName !: string; | 
					
						
							| 
									
										
										
										
											2018-05-09 16:49:39 -07:00
										 |  |  |       static ngComponentDef = defineComponent({ | 
					
						
							|  |  |  |         type: TestInputsComponent, | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |         encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-05-09 16:49:39 -07:00
										 |  |  |         selectors: [['test-inputs']], | 
					
						
							|  |  |  |         inputs: {minifiedName: 'unminifiedName'}, | 
					
						
							| 
									
										
										
										
											2018-08-16 18:53:21 -07:00
										 |  |  |         consts: 0, | 
					
						
							| 
									
										
										
										
											2018-08-18 11:14:50 -07:00
										 |  |  |         vars: 0, | 
					
						
							| 
									
										
										
										
											2018-05-09 16:49:39 -07:00
										 |  |  |         factory: () => new TestInputsComponent(), | 
					
						
							|  |  |  |         template: function(rf: RenderFlags, ctx: TestInputsComponent): void { | 
					
						
							|  |  |  |           // Template not needed for this test
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const testInputsComponentFactory = new ComponentFactory(TestInputsComponent.ngComponentDef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect([ | 
					
						
							|  |  |  |       {propName: 'minifiedName', templateName: 'unminifiedName'} | 
					
						
							|  |  |  |     ]).toEqual(testInputsComponentFactory.inputs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 11:48:09 -07:00
										 |  |  | }); |