@@ -299,6 +299,54 @@ describe('ngClass', function() {
299
299
expect ( e2 . hasClass ( 'D' ) ) . toBeFalsy ( ) ;
300
300
} ) ) ;
301
301
302
+ it ( 'should compute class names when changing row parity and class value' ,
303
+ inject ( function ( $rootScope , $compile ) {
304
+ element = $compile ( '<ul>' +
305
+ '<li ng-repeat="i in arr track by i" ng-class-even="cls"></li>' +
306
+ '</ul>' ) ( $rootScope ) ;
307
+
308
+ $rootScope . $apply ( function ( ) {
309
+ $rootScope . arr = [ 'a' , 'b' ] ;
310
+ $rootScope . cls = 'even' ;
311
+ } ) ;
312
+ var e3 = jqLite ( element [ 0 ] . childNodes [ 3 ] ) ;
313
+ expect ( e3 ) . toHaveClass ( 'even' ) ;
314
+
315
+ $rootScope . $apply ( function ( ) {
316
+ $rootScope . arr = [ 'b' ] ;
317
+ $rootScope . cls = 'off' ;
318
+ } ) ;
319
+ var e1 = jqLite ( element [ 0 ] . childNodes [ 1 ] ) ;
320
+ expect ( e3 [ 0 ] ) . toBe ( e1 [ 0 ] ) ; // make sure same instance of ngClassEven
321
+ expect ( e3 ) . not . toHaveClass ( 'even' ) ;
322
+ expect ( e3 ) . not . toHaveClass ( 'off' ) ;
323
+
324
+ $rootScope . $apply ( function ( ) {
325
+ $rootScope . arr = [ 'a' , 'b' ] ;
326
+ $rootScope . cls = 'on' ;
327
+ } ) ;
328
+ expect ( e3 ) . not . toHaveClass ( 'even' ) ;
329
+ expect ( e3 ) . not . toHaveClass ( 'off' ) ;
330
+ expect ( e3 ) . toHaveClass ( 'on' ) ;
331
+
332
+ // activate both $watch functions (class and $index)
333
+ // see https://plnkr.co/edit/W1ck8dS08TCJpirWiGVA
334
+ $rootScope . $apply ( function ( ) {
335
+ $rootScope . arr = [ 'b' ] ;
336
+ $rootScope . cls = 'off' ;
337
+ } ) ;
338
+ expect ( e3 ) . not . toHaveClass ( 'even' ) ;
339
+ expect ( e3 ) . not . toHaveClass ( 'off' ) ;
340
+ expect ( e3 ) . not . toHaveClass ( 'on' ) ;
341
+
342
+ $rootScope . $apply ( function ( ) {
343
+ $rootScope . arr = [ 'a' , 'b' ] ;
344
+ } ) ;
345
+ expect ( e3 ) . not . toHaveClass ( 'even' ) ;
346
+ expect ( e3 ) . toHaveClass ( 'off' ) ;
347
+ expect ( e3 ) . not . toHaveClass ( 'on' ) ;
348
+ } )
349
+ ) ;
302
350
303
351
it ( 'should reapply ngClass when interpolated class attribute changes' , inject ( function ( $rootScope , $compile ) {
304
352
element = $compile ( '<div class="one {{cls}} three" ng-class="{four: four}"></div>' ) ( $rootScope ) ;
@@ -424,6 +472,112 @@ describe('ngClass', function() {
424
472
} )
425
473
) ;
426
474
475
+ it ( 'should do value stabilization as expected when one-time binding' ,
476
+ inject ( function ( $rootScope , $compile ) {
477
+ element = $compile ( '<div ng-class=" :: className"></div>' ) ( $rootScope ) ;
478
+ $rootScope . $digest ( ) ;
479
+
480
+ $rootScope . className = 'foo' ;
481
+ $rootScope . $digest ( ) ;
482
+ expect ( element ) . toHaveClass ( 'foo' ) ;
483
+
484
+ $rootScope . className = 'bar' ;
485
+ $rootScope . $digest ( ) ;
486
+ expect ( element ) . toHaveClass ( 'foo' ) ;
487
+ } )
488
+ ) ;
489
+
490
+ it ( 'should remove the watcher when static array one-time binding' ,
491
+ inject ( function ( $rootScope , $compile ) {
492
+ element = $compile ( '<div ng-class="::[className]"></div>' ) ( $rootScope ) ;
493
+ $rootScope . $digest ( ) ;
494
+
495
+ $rootScope . className = 'foo' ;
496
+ $rootScope . $digest ( ) ;
497
+ expect ( element ) . toHaveClass ( 'foo' ) ;
498
+
499
+ $rootScope . className = 'bar' ;
500
+ $rootScope . $digest ( ) ;
501
+ expect ( element ) . toHaveClass ( 'foo' ) ;
502
+ expect ( element ) . not . toHaveClass ( 'bar' ) ;
503
+ } )
504
+ ) ;
505
+
506
+ it ( 'should remove the watcher when static map one-time binding' ,
507
+ inject ( function ( $rootScope , $compile ) {
508
+ element = $compile ( '<div ng-class="::{foo: fooPresent}"></div>' ) ( $rootScope ) ;
509
+ $rootScope . $digest ( ) ;
510
+
511
+ $rootScope . fooPresent = true ;
512
+ $rootScope . $digest ( ) ;
513
+ expect ( element ) . toHaveClass ( 'foo' ) ;
514
+
515
+ $rootScope . fooPresent = false ;
516
+ $rootScope . $digest ( ) ;
517
+ expect ( element ) . toHaveClass ( 'foo' ) ;
518
+ } )
519
+ ) ;
520
+
521
+ it ( 'should track changes of mutating object inside an array' ,
522
+ inject ( function ( $rootScope , $compile ) {
523
+ $rootScope . classVar = [ { orange : true } ] ;
524
+ element = $compile ( '<div ng-class="classVar"></div>' ) ( $rootScope ) ;
525
+ $rootScope . $digest ( ) ;
526
+ expect ( element ) . toHaveClass ( 'orange' ) ;
527
+
528
+ $rootScope . classVar [ 0 ] . orange = false ;
529
+ $rootScope . $digest ( ) ;
530
+
531
+ expect ( element ) . not . toHaveClass ( 'orange' ) ;
532
+ } )
533
+ ) ;
534
+
535
+ describe ( 'large objects' , function ( ) {
536
+
537
+ var verylargeobject , getProp ;
538
+ beforeEach ( function ( ) {
539
+ getProp = jasmine . createSpy ( 'getProp' ) ;
540
+ verylargeobject = { } ;
541
+ Object . defineProperty ( verylargeobject , 'prop' , {
542
+ get : getProp ,
543
+ enumerable : true
544
+ } ) ;
545
+ } ) ;
546
+
547
+ it ( 'should not be copied if static' , inject ( function ( $rootScope , $compile ) {
548
+ element = $compile ( '<div ng-class="{foo: verylargeobject}"></div>' ) ( $rootScope ) ;
549
+ $rootScope . verylargeobject = verylargeobject ;
550
+ $rootScope . $digest ( ) ;
551
+
552
+ expect ( getProp ) . not . toHaveBeenCalled ( ) ;
553
+ } ) ) ;
554
+
555
+ it ( 'should not be copied if dynamic' , inject ( function ( $rootScope , $compile ) {
556
+ $rootScope . fooClass = { foo : verylargeobject } ;
557
+ element = $compile ( '<div ng-class="fooClass"></div>' ) ( $rootScope ) ;
558
+ $rootScope . $digest ( ) ;
559
+
560
+ expect ( getProp ) . not . toHaveBeenCalled ( ) ;
561
+ } ) ) ;
562
+
563
+ it ( 'should not be copied if inside an array' , inject ( function ( $rootScope , $compile ) {
564
+ element = $compile ( '<div ng-class="[{foo: verylargeobject}]"></div>' ) ( $rootScope ) ;
565
+ $rootScope . verylargeobject = verylargeobject ;
566
+ $rootScope . $digest ( ) ;
567
+
568
+ expect ( getProp ) . not . toHaveBeenCalled ( ) ;
569
+ } ) ) ;
570
+
571
+ it ( 'should not be copied when one-time binding' , inject ( function ( $rootScope , $compile ) {
572
+ element = $compile ( '<div ng-class="::{foo: verylargeobject}"></div>' ) ( $rootScope ) ;
573
+ $rootScope . verylargeobject = verylargeobject ;
574
+ $rootScope . $digest ( ) ;
575
+
576
+ expect ( getProp ) . not . toHaveBeenCalled ( ) ;
577
+ } ) ) ;
578
+
579
+ } ) ;
580
+
427
581
} ) ;
428
582
429
583
describe ( 'ngClass animations' , function ( ) {
0 commit comments