| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'angular2/test_lib'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {DOM} from 'angular2/src/facade/dom'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {Injector} from 'angular2/di'; | 
					
						
							|  |  |  | import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler'; | 
					
						
							|  |  |  | import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader'; | 
					
						
							| 
									
										
										
										
											2015-01-30 09:43:21 +01:00
										 |  |  | import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations'; | 
					
						
							|  |  |  | import {TemplateConfig} from 'angular2/src/core/annotations/template_config'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {ViewPort} from 'angular2/src/core/compiler/viewport'; | 
					
						
							|  |  |  | import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  | import {Foreach} from 'angular2/src/directives/foreach'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function main() { | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |   describe('foreach', () => { | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     var view, cd, compiler, component; | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |       compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(), | 
					
						
							|  |  |  |         new Parser(new Lexer()), new CompilerCache(), new NativeShadowDomStrategy()); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function createView(pv) { | 
					
						
							|  |  |  |       component = new TestComponent(); | 
					
						
							|  |  |  |       view = pv.instantiate(null); | 
					
						
							|  |  |  |       view.hydrate(new Injector([]), null, component); | 
					
						
							| 
									
										
										
										
											2015-01-14 13:51:16 -08:00
										 |  |  |       cd = view.changeDetector; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function compileWithTemplate(template) { | 
					
						
							| 
									
										
										
										
											2015-01-08 09:11:33 -08:00
										 |  |  |       return compiler.compile(TestComponent, el(template)); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |     var TEMPLATE = '<div><copy-me template="foreach #item in items">{{item.toString()}};</copy-me></div>'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it('should reflect initial elements', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;2;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should reflect added elements', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ListWrapper.push(component.items, 3); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;2;3;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should reflect removed elements', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ListWrapper.removeAt(component.items, 1); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should reflect moved elements', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ListWrapper.removeAt(component.items, 0); | 
					
						
							|  |  |  |         ListWrapper.push(component.items, 1); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('2;1;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should reflect a mix of all changes (additions/removals/moves)', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         component.items = [0, 1, 2, 3, 4, 5]; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         component.items = [6, 2, 7, 0, 4, 8]; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('6;2;7;0;4;8;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should iterate over an array of objects', () => { | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |       compileWithTemplate('<ul><li template="foreach #item in items">{{item["name"]}};</li></ul>').then((pv) => { | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |         createView(pv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // INIT
 | 
					
						
							|  |  |  |         component.items = [{'name': 'misko'}, {'name':'shyam'}]; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('misko;shyam;'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // GROW
 | 
					
						
							|  |  |  |         ListWrapper.push(component.items, {'name': 'adam'}); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('misko;shyam;adam;'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // SHRINK
 | 
					
						
							|  |  |  |         ListWrapper.removeAt(component.items, 2); | 
					
						
							|  |  |  |         ListWrapper.removeAt(component.items, 0); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('shyam;'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should gracefully handle nulls', (done) => { | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |       compileWithTemplate('<ul><li template="foreach #item in null">{{item}};</li></ul>').then((pv) => { | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual(''); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should gracefully handle ref changing to null and back', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;2;'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         component.items = null; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual(''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         component.items = [1, 2, 3]; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;2;3;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should throw on ref changing to string', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('1;2;'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         component.items = 'whaaa'; | 
					
						
							|  |  |  |         expect(() => cd.detectChanges()).toThrowError(); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should works with duplicates', (done) => { | 
					
						
							|  |  |  |       compileWithTemplate(TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |         createView(pv); | 
					
						
							|  |  |  |         var a = new Foo(); | 
					
						
							|  |  |  |         component.items = [a, a]; | 
					
						
							|  |  |  |         cd.detectChanges(); | 
					
						
							|  |  |  |         expect(DOM.getText(view.nodes[0])).toEqual('foo;foo;'); | 
					
						
							|  |  |  |         done(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should repeat over nested arrays', (done) => { | 
					
						
							|  |  |  |     compileWithTemplate( | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |         '<div><div template="foreach #item in items">' + | 
					
						
							|  |  |  |           '<div template="foreach #subitem in item">' + | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |           '{{subitem}};' + | 
					
						
							| 
									
										
										
										
											2014-12-12 10:31:34 -08:00
										 |  |  |         '</div>|</div></div>' | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     ).then((pv) => { | 
					
						
							|  |  |  |       createView(pv); | 
					
						
							|  |  |  |       component.items = [['a', 'b'], ['c','d']]; | 
					
						
							|  |  |  |       cd.detectChanges(); | 
					
						
							|  |  |  |       cd.detectChanges(); | 
					
						
							|  |  |  |       cd.detectChanges(); | 
					
						
							| 
									
										
										
										
											2014-12-12 10:31:34 -08:00
										 |  |  |       expect(DOM.getText(view.nodes[0])).toEqual('a;b;|c;d;|'); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       done(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-28 00:42:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   it('should display indices correctly', (done) => { | 
					
						
							| 
									
										
										
										
											2015-01-27 22:34:25 -08:00
										 |  |  |     var INDEX_TEMPLATE = | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |       '<div><copy-me template="foreach: var item in items; var i=index">{{i.toString()}}</copy-me></div>'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     compileWithTemplate(INDEX_TEMPLATE).then((pv) => { | 
					
						
							|  |  |  |       createView(pv); | 
					
						
							|  |  |  |       component.items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; | 
					
						
							|  |  |  |       cd.detectChanges(); | 
					
						
							|  |  |  |       expect(DOM.getText(view.nodes[0])).toEqual('0123456789'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       component.items = [1, 2, 6, 7, 4, 3, 5, 8, 9, 0]; | 
					
						
							|  |  |  |       cd.detectChanges(); | 
					
						
							|  |  |  |       expect(DOM.getText(view.nodes[0])).toEqual('0123456789'); | 
					
						
							|  |  |  |       done(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2015-01-28 00:42:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Foo { | 
					
						
							|  |  |  |   toString() { | 
					
						
							|  |  |  |     return 'foo'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'test-cmp', | 
					
						
							|  |  |  |   template: new TemplateConfig({ | 
					
						
							|  |  |  |     inline: '',  // each test swaps with a custom template.
 | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |     directives: [Foreach] | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   }) | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class TestComponent { | 
					
						
							|  |  |  |   items: any; | 
					
						
							|  |  |  |   item: any; | 
					
						
							|  |  |  |   constructor() { | 
					
						
							|  |  |  |     this.items = [1, 2]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |