diff options
| author | jankuca | 2013-09-23 11:24:42 -0700 |
|---|---|---|
| committer | Vojta Jina | 2013-10-09 15:19:10 -0700 |
| commit | 9efa46ae640cde17487c341daa9a75c0bd79da02 (patch) | |
| tree | addebed6c08a10e5f27a99140d3f5846992d43a2 /test/ng | |
| parent | 64fd2c421ed582c16812d164a8a6f031b8e66287 (diff) | |
| download | angular.js-9efa46ae640cde17487c341daa9a75c0bd79da02.tar.bz2 | |
feat(ngRepeat): use block separator comments
Issue: multi-elements ng-repeat (ng-repeat-start, ng-repeat-end) can contain elements with a trancluding directive. This directive changes content of the row (template) and ng-repeat does not work correctly (when removing/moving rows), because ng-repeat works with the original template (elements).
This changes ng-repeat behavior to traverse the DOM to find current elements everytime we are moving/removing rows (if the template has multiple elements).
Closes #3104
Diffstat (limited to 'test/ng')
| -rw-r--r-- | test/ng/directive/ngClassSpec.js | 10 | ||||
| -rw-r--r-- | test/ng/directive/ngRepeatSpec.js | 163 |
2 files changed, 152 insertions, 21 deletions
diff --git a/test/ng/directive/ngClassSpec.js b/test/ng/directive/ngClassSpec.js index f0989f4a..a788e452 100644 --- a/test/ng/directive/ngClassSpec.js +++ b/test/ng/directive/ngClassSpec.js @@ -166,7 +166,7 @@ describe('ngClass', function() { element = $compile('<ul><li ng-repeat="i in [0,1]" class="existing" ng-class-odd="\'odd\'" ng-class-even="\'even\'"></li><ul>')($rootScope); $rootScope.$digest(); var e1 = jqLite(element[0].childNodes[1]); - var e2 = jqLite(element[0].childNodes[2]); + var e2 = jqLite(element[0].childNodes[3]); expect(e1.hasClass('existing')).toBeTruthy(); expect(e1.hasClass('odd')).toBeTruthy(); expect(e2.hasClass('existing')).toBeTruthy(); @@ -181,7 +181,7 @@ describe('ngClass', function() { '<ul>')($rootScope); $rootScope.$apply(); var e1 = jqLite(element[0].childNodes[1]); - var e2 = jqLite(element[0].childNodes[2]); + var e2 = jqLite(element[0].childNodes[3]); expect(e1.hasClass('plainClass')).toBeTruthy(); expect(e1.hasClass('odd')).toBeTruthy(); @@ -199,7 +199,7 @@ describe('ngClass', function() { '<ul>')($rootScope); $rootScope.$apply(); var e1 = jqLite(element[0].childNodes[1]); - var e2 = jqLite(element[0].childNodes[2]); + var e2 = jqLite(element[0].childNodes[3]); expect(e1.hasClass('A')).toBeTruthy(); expect(e1.hasClass('B')).toBeTruthy(); @@ -273,7 +273,7 @@ describe('ngClass', function() { $rootScope.$digest(); var e1 = jqLite(element[0].childNodes[1]); - var e2 = jqLite(element[0].childNodes[2]); + var e2 = jqLite(element[0].childNodes[3]); expect(e1.hasClass('odd')).toBeTruthy(); expect(e1.hasClass('even')).toBeFalsy(); @@ -295,7 +295,7 @@ describe('ngClass', function() { $rootScope.$digest(); var e1 = jqLite(element[0].childNodes[1]); - var e2 = jqLite(element[0].childNodes[2]); + var e2 = jqLite(element[0].childNodes[3]); expect(e1.hasClass('odd')).toBeTruthy(); expect(e1.hasClass('even')).toBeFalsy(); diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index 4cf79dbf..8dba13bf 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -621,7 +621,9 @@ describe('ngRepeat', function() { '<div>' + '<!-- ngRepeat: i in items -->' + '<div ng-repeat="i in items" rr="">1|</div>' + + '<!-- end ngRepeat: i in items -->' + '<div ng-repeat="i in items" rr="">2|</div>' + + '<!-- end ngRepeat: i in items -->' + '</div>' ); })); @@ -651,7 +653,9 @@ describe('ngRepeat', function() { '<div>' + '<!-- ngRepeat: i in items -->' + '<div ng-repeat="i in items" rr="">1|</div>' + + '<!-- end ngRepeat: i in items -->' + '<div ng-repeat="i in items" rr="">2|</div>' + + '<!-- end ngRepeat: i in items -->' + '</div>' ); })); @@ -748,6 +752,106 @@ describe('ngRepeat', function() { }); + it('should add separator comments after each item', inject(function ($compile, $rootScope) { + var check = function () { + var children = element.find('div'); + expect(children.length).toBe(3); + + // Note: COMMENT_NODE === 8 + expect(children[0].nextSibling.nodeType).toBe(8); + expect(children[0].nextSibling.nodeValue).toBe(' end ngRepeat: val in values '); + expect(children[1].nextSibling.nodeType).toBe(8); + expect(children[1].nextSibling.nodeValue).toBe(' end ngRepeat: val in values '); + expect(children[2].nextSibling.nodeType).toBe(8); + expect(children[2].nextSibling.nodeValue).toBe(' end ngRepeat: val in values '); + } + + $rootScope.values = [1, 2, 3]; + + element = $compile( + '<div>' + + '<div ng-repeat="val in values">val:{{val}};</div>' + + '</div>' + )($rootScope); + + $rootScope.$digest(); + check(); + + $rootScope.values.shift(); + $rootScope.values.push(4); + $rootScope.$digest(); + check(); + })); + + + it('should remove whole block even if the number of elements inside it changes', inject( + function ($compile, $rootScope) { + + $rootScope.values = [1, 2, 3]; + + element = $compile( + '<div>' + + '<div ng-repeat-start="val in values"></div>' + + '<span>{{val}}</span>' + + '<p ng-repeat-end></p>' + + '</div>' + )($rootScope); + + $rootScope.$digest(); + + var ends = element.find('p'); + expect(ends.length).toBe(3); + + // insert an extra element inside the second block + var extra = angular.element('<strong></strong>')[0]; + element[0].insertBefore(extra, ends[1]); + + $rootScope.values.splice(1, 1); + $rootScope.$digest(); + + // expect the strong tag to be removed too + expect(childrenTagsOf(element)).toEqual([ + 'div', 'span', 'p', + 'div', 'span', 'p' + ]); + })); + + + it('should move whole block even if the number of elements inside it changes', inject( + function ($compile, $rootScope) { + + $rootScope.values = [1, 2, 3]; + + element = $compile( + '<div>' + + '<div ng-repeat-start="val in values"></div>' + + '<span>{{val}}</span>' + + '<p ng-repeat-end></p>' + + '</div>' + )($rootScope); + + $rootScope.$digest(); + + var ends = element.find('p'); + expect(ends.length).toBe(3); + + // insert an extra element inside the third block + var extra = angular.element('<strong></strong>')[0]; + element[0].insertBefore(extra, ends[2]); + + // move the third block to the begining + $rootScope.values.unshift($rootScope.values.pop()); + $rootScope.$digest(); + + // expect the strong tag to be moved too + expect(childrenTagsOf(element)).toEqual([ + 'div', 'span', 'strong', 'p', + 'div', 'span', 'p', + 'div', 'span', 'p' + ]); + })); + + describe('stability', function() { var a, b, c, d, lis; @@ -871,26 +975,53 @@ describe('ngRepeat', function() { }); }); - it('should grow multi-node repeater', inject(function($compile, $rootScope) { - $rootScope.show = false; - $rootScope.books = [ - {title:'T1', description: 'D1'}, - {title:'T2', description: 'D2'} - ]; - element = $compile( + + describe('ngRepeatStart', function () { + it('should grow multi-node repeater', inject(function($compile, $rootScope) { + $rootScope.show = false; + $rootScope.books = [ + {title:'T1', description: 'D1'}, + {title:'T2', description: 'D2'} + ]; + element = $compile( + '<div>' + + '<dt ng-repeat-start="book in books">{{book.title}}:</dt>' + + '<dd ng-repeat-end>{{book.description}};</dd>' + + '</div>')($rootScope); + + $rootScope.$digest(); + expect(element.text()).toEqual('T1:D1;T2:D2;'); + $rootScope.books.push({title:'T3', description: 'D3'}); + $rootScope.$digest(); + expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;'); + })); + + + it('should not clobber ng-if when updating collection', inject(function ($compile, $rootScope) { + $rootScope.values = [1, 2, 3]; + $rootScope.showMe = true; + + element = $compile( '<div>' + - '<dt ng-repeat-start="book in books">{{book.title}}:</dt>' + - '<dd ng-repeat-end>{{book.description}};</dd>' + - '</div>')($rootScope); + '<div ng-repeat-start="val in values">val:{{val}};</div>' + + '<div ng-if="showMe" ng-repeat-end>if:{{val}};</div>' + + '</div>' + )($rootScope); - $rootScope.$digest(); - expect(element.text()).toEqual('T1:D1;T2:D2;'); - $rootScope.books.push({title:'T3', description: 'D3'}); - $rootScope.$digest(); - expect(element.text()).toEqual('T1:D1;T2:D2;T3:D3;'); - })); + $rootScope.$digest(); + expect(element.find('div').length).toBe(6); + + $rootScope.values.shift(); + $rootScope.values.push(4); + + $rootScope.$digest(); + expect(element.find('div').length).toBe(6); + expect(element.text()).not.toContain('if:1;'); + })); + }); }); + describe('ngRepeat animations', function() { var body, element, $rootElement; |
