| OLD | NEW |
| (Empty) | |
| 1 library ng_repeat_spec; |
| 2 |
| 3 import '../_specs.dart'; |
| 4 |
| 5 main() { |
| 6 describe('NgRepeater', () { |
| 7 var element, $compile, scope, $exceptionHandler; |
| 8 |
| 9 beforeEach(inject((Injector injector, Scope $rootScope, Compiler compiler) { |
| 10 $exceptionHandler = injector.get(ExceptionHandler); |
| 11 scope = $rootScope; |
| 12 $compile = (html) { |
| 13 element = $(html); |
| 14 var blockFactory = compiler(element); |
| 15 var block = blockFactory(injector, element); |
| 16 return element; |
| 17 }; |
| 18 })); |
| 19 |
| 20 it(r'should set create a list of items', inject((Scope scope, Compiler compi
ler, Injector injector) { |
| 21 var element = $('<div><div ng-repeat="item in items">{{item}}</div></div>'
); |
| 22 BlockFactory blockFactory = compiler(element); |
| 23 Block block = blockFactory(injector, element); |
| 24 scope.items = ['a', 'b']; |
| 25 scope.$apply(); |
| 26 expect(element.text()).toEqual('ab'); |
| 27 })); |
| 28 |
| 29 |
| 30 it(r'should set create a list of items from iterable', |
| 31 inject((Scope scope, Compiler compiler, Injector injector) { |
| 32 var element = $('<div><div ng-repeat="item in items">{{item}}</div></div>'
); |
| 33 BlockFactory blockFactory = compiler(element); |
| 34 Block block = blockFactory(injector, element); |
| 35 scope.items = ['a', 'b'].map((i) => i); // makes an iterable |
| 36 scope.$apply(); |
| 37 expect(element.text()).toEqual('ab'); |
| 38 })); |
| 39 |
| 40 |
| 41 it(r'should iterate over an array of objects', () { |
| 42 element = $compile( |
| 43 '<ul>' + |
| 44 '<li ng-repeat="item in items">{{item.name}};</li>' + |
| 45 '</ul>'); |
| 46 |
| 47 // INIT |
| 48 scope.items = [{"name": 'misko'}, {"name":'shyam'}]; |
| 49 scope.$digest(); |
| 50 expect(element.find('li').length).toEqual(2); |
| 51 expect(element.text()).toEqual('misko;shyam;'); |
| 52 |
| 53 // GROW |
| 54 scope.items.add({"name": 'adam'}); |
| 55 scope.$digest(); |
| 56 expect(element.find('li').length).toEqual(3); |
| 57 expect(element.text()).toEqual('misko;shyam;adam;'); |
| 58 |
| 59 // SHRINK |
| 60 scope.items.removeLast(); |
| 61 scope.items.removeAt(0); |
| 62 scope.$digest(); |
| 63 expect(element.find('li').length).toEqual(1); |
| 64 expect(element.text()).toEqual('shyam;'); |
| 65 }); |
| 66 |
| 67 |
| 68 it(r'should gracefully handle nulls', () { |
| 69 element = $compile( |
| 70 '<div>' + |
| 71 '<ul>' + |
| 72 '<li ng-repeat="item in null">{{item.name}};</li>' + |
| 73 '</ul>' + |
| 74 '</div>'); |
| 75 scope.$digest(); |
| 76 expect(element.find('ul').length).toEqual(1); |
| 77 expect(element.find('li').length).toEqual(0); |
| 78 }); |
| 79 |
| 80 |
| 81 describe('track by', () { |
| 82 it(r'should track using expression function', () { |
| 83 element = $compile( |
| 84 '<ul>' + |
| 85 '<li ng-repeat="item in items track by item.id">{{item.name}};</
li>' + |
| 86 '</ul>'); |
| 87 scope.items = [{"id": 'misko'}, {"id": 'igor'}]; |
| 88 scope.$digest(); |
| 89 var li0 = element.find('li')[0]; |
| 90 var li1 = element.find('li')[1]; |
| 91 |
| 92 scope.items.add(scope.items.removeAt(0)); |
| 93 scope.$digest(); |
| 94 expect(element.find('li')[0]).toBe(li1); |
| 95 expect(element.find('li')[1]).toBe(li0); |
| 96 }); |
| 97 |
| 98 |
| 99 it(r'should track using build in $id function', () { |
| 100 element = $compile( |
| 101 '<ul>' + |
| 102 r'<li ng-repeat="item in items track by $id(item)">{{item.name}}
;</li>' + |
| 103 '</ul>'); |
| 104 scope.items = [{"name": 'misko'}, {"name": 'igor'}]; |
| 105 scope.$digest(); |
| 106 var li0 = element.find('li')[0]; |
| 107 var li1 = element.find('li')[1]; |
| 108 |
| 109 scope.items.add(scope.items.removeAt(0)); |
| 110 scope.$digest(); |
| 111 expect(element.find('li')[0]).toBe(li1); |
| 112 expect(element.find('li')[1]).toBe(li0); |
| 113 }); |
| 114 |
| 115 |
| 116 xit(r'should iterate over an array of primitives', () { |
| 117 element = $compile( |
| 118 r'<ul>' + |
| 119 r'<li ng-repeat="item in items track by $index">{{item}};</li>'
+ |
| 120 r'</ul>'); |
| 121 |
| 122 // INIT |
| 123 scope.items = [true, true, true]; |
| 124 scope.$digest(); |
| 125 expect(element.find('li').length).toEqual(3); |
| 126 expect(element.text()).toEqual('true;true;true;'); |
| 127 |
| 128 scope.items = [false, true, true]; |
| 129 scope.$digest(); |
| 130 expect(element.find('li').length).toEqual(3); |
| 131 expect(element.text()).toEqual('false;true;true;'); |
| 132 |
| 133 scope.items = [false, true, false]; |
| 134 scope.$digest(); |
| 135 expect(element.find('li').length).toEqual(3); |
| 136 expect(element.text()).toEqual('false;true;false;'); |
| 137 |
| 138 scope.items = [true]; |
| 139 scope.$digest(); |
| 140 expect(element.find('li').length).toEqual(1); |
| 141 expect(element.text()).toEqual('true;'); |
| 142 |
| 143 scope.items = [true, true, false]; |
| 144 scope.$digest(); |
| 145 expect(element.find('li').length).toEqual(3); |
| 146 expect(element.text()).toEqual('true;true;false;'); |
| 147 |
| 148 scope.items = [true, false, false]; |
| 149 scope.$digest(); |
| 150 expect(element.find('li').length).toEqual(3); |
| 151 expect(element.text()).toEqual('true;false;false;'); |
| 152 |
| 153 // string |
| 154 scope.items = ['a', 'a', 'a']; |
| 155 scope.$digest(); |
| 156 expect(element.find('li').length).toEqual(3); |
| 157 expect(element.text()).toEqual('a;a;a;'); |
| 158 |
| 159 scope.items = ['ab', 'a', 'a']; |
| 160 scope.$digest(); |
| 161 expect(element.find('li').length).toEqual(3); |
| 162 expect(element.text()).toEqual('ab;a;a;'); |
| 163 |
| 164 scope.items = ['test']; |
| 165 scope.$digest(); |
| 166 expect(element.find('li').length).toEqual(1); |
| 167 expect(element.text()).toEqual('test;'); |
| 168 |
| 169 scope.items = ['same', 'value']; |
| 170 scope.$digest(); |
| 171 expect(element.find('li').length).toEqual(2); |
| 172 expect(element.text()).toEqual('same;value;'); |
| 173 |
| 174 // number |
| 175 scope.items = [12, 12, 12]; |
| 176 scope.$digest(); |
| 177 expect(element.find('li').length).toEqual(3); |
| 178 expect(element.text()).toEqual('12;12;12;'); |
| 179 |
| 180 scope.items = [53, 12, 27]; |
| 181 scope.$digest(); |
| 182 expect(element.find('li').length).toEqual(3); |
| 183 expect(element.text()).toEqual('53;12;27;'); |
| 184 |
| 185 scope.items = [89]; |
| 186 scope.$digest(); |
| 187 expect(element.find('li').length).toEqual(1); |
| 188 expect(element.text()).toEqual('89;'); |
| 189 |
| 190 scope.items = [89, 23]; |
| 191 scope.$digest(); |
| 192 expect(element.find('li').length).toEqual(2); |
| 193 expect(element.text()).toEqual('89;23;'); |
| 194 }); |
| 195 |
| 196 }); |
| 197 |
| 198 |
| 199 it(r'should error on wrong parsing of ngRepeat', () { |
| 200 element = $('<ul><li ng-repeat="i dont parse"></li></ul>'); |
| 201 expect(() { |
| 202 $compile(element); |
| 203 }).toThrow("[NgErr7] ngRepeat error! Expected expression in form of '_item
_ in _collection_[ track by _id_]' but got 'i dont parse'."); |
| 204 }); |
| 205 |
| 206 |
| 207 it("should throw error when left-hand-side of ngRepeat can't be parsed", ()
{ |
| 208 element = $('<ul><li ng-repeat="i dont parse in foo"></li></ul>'); |
| 209 expect(() { |
| 210 $compile(element); |
| 211 }).toThrow("[NgErr8] ngRepeat error! '_item_' in '_item_ in _collection_
' should be an identifier or '(_key_, _value_)' expression, but got 'i dont pars
e'."); |
| 212 }); |
| 213 |
| 214 |
| 215 it(r'should expose iterator offset as $index when iterating over arrays', |
| 216 () { |
| 217 element = $compile( |
| 218 '<ul>' + |
| 219 '<li ng-repeat="item in items">{{item}}:{{\$index}}|</li>' + |
| 220 '</ul>'); |
| 221 scope.items = ['misko', 'shyam', 'frodo']; |
| 222 scope.$digest(); |
| 223 expect(element.text()).toEqual('misko:0|shyam:1|frodo:2|'); |
| 224 }); |
| 225 |
| 226 |
| 227 it(r'should expose iterator position as $first, $middle and $last when itera
ting over arrays', |
| 228 () { |
| 229 element = $compile( |
| 230 '<ul>' + |
| 231 '<li ng-repeat="item in items">{{item}}:{{\$first}}-{{\$middle}}-{{\$l
ast}}|</li>' + |
| 232 '</ul>'); |
| 233 scope.items = ['misko', 'shyam', 'doug']; |
| 234 scope.$digest(); |
| 235 expect(element.text()). |
| 236 toEqual('misko:true-false-false|shyam:false-true-false|doug:false-fals
e-true|'); |
| 237 |
| 238 scope.items.add('frodo'); |
| 239 scope.$digest(); |
| 240 expect(element.text()). |
| 241 toEqual('misko:true-false-false|' + |
| 242 'shyam:false-true-false|' + |
| 243 'doug:false-true-false|' + |
| 244 'frodo:false-false-true|'); |
| 245 |
| 246 scope.items.removeLast(); |
| 247 scope.items.removeLast(); |
| 248 scope.$digest(); |
| 249 expect(element.text()).toEqual('misko:true-false-false|shyam:false-false-t
rue|'); |
| 250 |
| 251 scope.items.removeLast(); |
| 252 scope.$digest(); |
| 253 expect(element.text()).toEqual('misko:true-false-true|'); |
| 254 }); |
| 255 |
| 256 it(r'should report odd', () { |
| 257 element = $compile( |
| 258 '<ul>' + |
| 259 '<li ng-repeat="item in items">{{item}}:{{\$odd}}-{{\$even}}|</li>' + |
| 260 '</ul>'); |
| 261 scope.items = ['misko', 'shyam', 'doug']; |
| 262 scope.$digest(); |
| 263 expect(element.text()).toEqual('misko:false-true|shyam:true-false|doug:fal
se-true|'); |
| 264 |
| 265 scope.items.add('frodo'); |
| 266 scope.$digest(); |
| 267 expect(element.text()).toEqual('misko:false-true|shyam:true-false|doug:fal
se-true|frodo:true-false|'); |
| 268 |
| 269 scope.items.removeLast(); |
| 270 scope.items.removeLast(); |
| 271 scope.$digest(); |
| 272 expect(element.text()).toEqual('misko:false-true|shyam:true-false|'); |
| 273 |
| 274 scope.items.removeLast(); |
| 275 scope.$digest(); |
| 276 expect(element.text()).toEqual('misko:false-true|'); |
| 277 }); |
| 278 |
| 279 it(r'should repeat over nested arrays', () { |
| 280 element = $compile( |
| 281 '<ul>' + |
| 282 '<li ng-repeat="subgroup in groups">' + |
| 283 '<div ng-repeat="group in subgroup">{{group}}|</div>X' + |
| 284 '</li>' + |
| 285 '</ul>'); |
| 286 scope.groups = [['a', 'b'], ['c','d']]; |
| 287 scope.$digest(); |
| 288 |
| 289 expect(element.text()).toEqual('a|b|Xc|d|X'); |
| 290 }); |
| 291 |
| 292 |
| 293 describe('stability', () { |
| 294 var a, b, c, d, lis; |
| 295 |
| 296 beforeEach(() { |
| 297 element = $compile( |
| 298 '<ul>' + |
| 299 '<li ng-repeat="item in items">{{key}}:{{val}}|></li>' + |
| 300 '</ul>'); |
| 301 a = {}; |
| 302 b = {}; |
| 303 c = {}; |
| 304 d = {}; |
| 305 |
| 306 scope.items = [a, b, c]; |
| 307 scope.$digest(); |
| 308 lis = element.find('li'); |
| 309 }); |
| 310 |
| 311 |
| 312 it(r'should preserve the order of elements', () { |
| 313 scope.items = [a, c, d]; |
| 314 scope.$digest(); |
| 315 var newElements = element.find('li'); |
| 316 expect(newElements[0]).toEqual(lis[0]); |
| 317 expect(newElements[1]).toEqual(lis[2]); |
| 318 expect(newElements[2] == lis[1]).toEqual(false); |
| 319 }); |
| 320 |
| 321 |
| 322 it(r'should throw error on adding existing duplicates and recover', () { |
| 323 scope.items = [a, a, a]; |
| 324 expect(() { |
| 325 scope.$digest(); |
| 326 }).toThrow("[NgErr50] ngRepeat error! Duplicates in a repeater are not a
llowed. Use 'track by' expression to specify unique keys. Repeater: item in item
s, Duplicate key: {}"); |
| 327 |
| 328 // recover |
| 329 scope.items = [a]; |
| 330 scope.$digest(); |
| 331 var newElements = element.find('li'); |
| 332 expect(newElements.length).toEqual(1); |
| 333 expect(newElements[0]).toEqual(lis[0]); |
| 334 |
| 335 scope.items = []; |
| 336 scope.$digest(); |
| 337 newElements = element.find('li'); |
| 338 expect(newElements.length).toEqual(0); |
| 339 }); |
| 340 |
| 341 |
| 342 it(r'should throw error on new duplicates and recover', () { |
| 343 scope.items = [d, d, d]; |
| 344 expect(() { |
| 345 scope.$digest(); |
| 346 }).toThrow("[NgErr50] ngRepeat error! Duplicates in a repeater are not a
llowed. Use 'track by' expression to specify unique keys. Repeater: item in item
s, Duplicate key: {}"); |
| 347 |
| 348 // recover |
| 349 scope.items = [a]; |
| 350 scope.$digest(); |
| 351 var newElements = element.find('li'); |
| 352 expect(newElements.length).toEqual(1); |
| 353 expect(newElements[0]).toEqual(lis[0]); |
| 354 |
| 355 scope.items = []; |
| 356 scope.$digest(); |
| 357 newElements = element.find('li'); |
| 358 expect(newElements.length).toEqual(0); |
| 359 }); |
| 360 |
| 361 |
| 362 it(r'should reverse items when the collection is reversed', () { |
| 363 scope.items = [a, b, c]; |
| 364 scope.$digest(); |
| 365 lis = element.find('li'); |
| 366 |
| 367 scope.items = [c, b, a]; |
| 368 scope.$digest(); |
| 369 var newElements = element.find('li'); |
| 370 expect(newElements.length).toEqual(3); |
| 371 expect(newElements[0]).toEqual(lis[2]); |
| 372 expect(newElements[1]).toEqual(lis[1]); |
| 373 expect(newElements[2]).toEqual(lis[0]); |
| 374 }); |
| 375 |
| 376 |
| 377 it(r'should reuse elements even when model is composed of primitives', ()
{ |
| 378 // rebuilding repeater from scratch can be expensive, we should try to a
void it even for |
| 379 // model that is composed of primitives. |
| 380 |
| 381 scope.items = ['hello', 'cau', 'ahoj']; |
| 382 scope.$digest(); |
| 383 lis = element.find('li'); |
| 384 lis[2].id = 'yes'; |
| 385 |
| 386 scope.items = ['ahoj', 'hello', 'cau']; |
| 387 scope.$digest(); |
| 388 var newLis = element.find('li'); |
| 389 expect(newLis.length).toEqual(3); |
| 390 expect(newLis[0]).toEqual(lis[2]); |
| 391 expect(newLis[1]).toEqual(lis[0]); |
| 392 expect(newLis[2]).toEqual(lis[1]); |
| 393 }); |
| 394 }); |
| 395 |
| 396 describe('shalow', () { |
| 397 TestBed _; |
| 398 beforeEach(inject((TestBed tb) => _ = tb)); |
| 399 |
| 400 it('should x', () { |
| 401 _.compile('<ul><li ng-shallow-repeat="i in items">{{i.name}}</li></ul>')
; |
| 402 _.rootScope.items = [{'name': 'a'}, {'name':'b'}]; |
| 403 _.rootScope.$digest(); |
| 404 expect(_.rootElement.text).toEqual('ab'); |
| 405 |
| 406 // Should not see this. |
| 407 _.rootScope.items[0]['name'] = 'x'; |
| 408 _.rootScope.$digest(); |
| 409 expect(_.rootElement.text).toEqual('ab'); |
| 410 |
| 411 // We see additions but not changse |
| 412 _.rootScope.items.add({'name': 'C'}); |
| 413 _.rootScope.$digest(); |
| 414 expect(_.rootElement.text).toEqual('abC'); |
| 415 |
| 416 |
| 417 // Cloning list does a full update |
| 418 _.rootScope.items = new List.from(_.rootScope.items); |
| 419 _.rootScope.$digest(); |
| 420 expect(_.rootElement.text).toEqual('xbC'); |
| 421 }); |
| 422 }); |
| 423 }); |
| 424 } |
| OLD | NEW |