2012-03-08 23:00:38 +00:00
'use strict' ;
2012-04-09 18:20:55 +00:00
describe ( 'ngRepeat' , function ( ) {
2013-03-13 23:29:26 +00:00
var element , $compile , scope , $exceptionHandler , $compileProvider ;
beforeEach ( module ( function ( _$compileProvider _ ) {
$compileProvider = _$compileProvider _ ;
} ) ) ;
2012-11-23 15:08:47 +00:00
2013-03-20 05:27:27 +00:00
beforeEach ( module ( function ( $exceptionHandlerProvider ) {
$exceptionHandlerProvider . mode ( 'log' ) ;
} ) ) ;
beforeEach ( inject ( function ( _$compile _ , $rootScope , _$exceptionHandler _ ) {
2012-11-23 15:08:47 +00:00
$compile = _$compile _ ;
2013-03-20 05:27:27 +00:00
$exceptionHandler = _$exceptionHandler _ ;
2012-11-23 15:08:47 +00:00
scope = $rootScope . $new ( ) ;
} ) ) ;
2012-03-08 23:00:38 +00:00
2013-03-20 05:27:27 +00:00
afterEach ( function ( ) {
if ( $exceptionHandler . errors . length ) {
dump ( jasmine . getEnv ( ) . currentSpec . getFullName ( ) ) ;
dump ( '$exceptionHandler has errors' ) ;
dump ( $exceptionHandler . errors ) ;
expect ( $exceptionHandler . errors ) . toBe ( [ ] ) ;
}
2012-03-08 23:00:38 +00:00
dealoc ( element ) ;
} ) ;
2012-11-23 15:08:47 +00:00
it ( 'should iterate over an array of objects' , function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-11-23 15:08:47 +00:00
'<li ng-repeat="item in items">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
2012-03-08 23:00:38 +00:00
Array . prototype . extraProperty = "should be ignored" ;
// INIT
2012-11-23 15:08:47 +00:00
scope . items = [ { name : 'misko' } , { name : 'shyam' } ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . find ( 'li' ) . length ) . toEqual ( 2 ) ;
expect ( element . text ( ) ) . toEqual ( 'misko;shyam;' ) ;
delete Array . prototype . extraProperty ;
// GROW
2012-11-23 15:08:47 +00:00
scope . items . push ( { name : 'adam' } ) ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
2012-11-23 15:08:47 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko;shyam;adam;' ) ;
2012-03-08 23:00:38 +00:00
// SHRINK
2012-11-23 15:08:47 +00:00
scope . items . pop ( ) ;
scope . items . shift ( ) ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . find ( 'li' ) . length ) . toEqual ( 1 ) ;
2012-11-23 15:08:47 +00:00
expect ( element . text ( ) ) . toEqual ( 'shyam;' ) ;
} ) ;
2012-03-08 23:00:38 +00:00
2013-04-30 23:19:44 +00:00
it ( 'should iterate over an array-like object' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="item in items">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
document . body . innerHTML = "<p>" +
"<a name='x'>a</a>" +
"<a name='y'>b</a>" +
"<a name='x'>c</a>" +
"</p>" ;
2013-06-28 07:28:06 +00:00
var htmlCollection = document . getElementsByTagName ( 'a' ) ;
2013-04-30 23:19:44 +00:00
scope . items = htmlCollection ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'x;y;x;' ) ;
} ) ;
2013-08-13 22:30:52 +00:00
2013-07-26 03:15:57 +00:00
it ( 'should iterate over an array-like class' , function ( ) {
function Collection ( ) { }
Collection . prototype = new Array ( ) ;
Collection . prototype . length = 0 ;
2013-04-30 23:19:44 +00:00
2013-07-26 03:15:57 +00:00
var collection = new Collection ( ) ;
collection . push ( { name : "x" } ) ;
collection . push ( { name : "y" } ) ;
collection . push ( { name : "z" } ) ;
element = $compile (
'<ul>' +
'<li ng-repeat="item in items">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = collection ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'x;y;z;' ) ;
} ) ;
2013-04-30 23:19:44 +00:00
2013-03-20 05:27:27 +00:00
it ( 'should iterate over on object/map' , function ( ) {
2012-05-08 21:00:38 +00:00
element = $compile (
'<ul>' +
2013-03-20 05:27:27 +00:00
'<li ng-repeat="(key, value) in items">{{key}}:{{value}}|</li>' +
2012-11-23 15:08:47 +00:00
'</ul>' ) ( scope ) ;
2013-03-20 05:27:27 +00:00
scope . items = { misko : 'swe' , shyam : 'set' } ;
2012-11-23 15:08:47 +00:00
scope . $digest ( ) ;
2013-03-20 05:27:27 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko:swe|shyam:set|' ) ;
} ) ;
2012-05-08 21:00:38 +00:00
2013-05-27 17:59:19 +00:00
it ( 'should iterate over an object/map with identical values' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="(key, value) in items">{{key}}:{{value}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = { age : 20 , wealth : 20 , prodname : "Bingo" , dogname : "Bingo" , codename : "20" } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toEqual ( 'age:20|codename:20|dogname:Bingo|prodname:Bingo|wealth:20|' ) ;
} ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
describe ( 'track by' , function ( ) {
it ( 'should track using expression function' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="item in items track by item.id">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ { id : 'misko' } , { id : 'igor' } ] ;
scope . $digest ( ) ;
var li0 = element . find ( 'li' ) [ 0 ] ;
var li1 = element . find ( 'li' ) [ 1 ] ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items . push ( scope . items . shift ( ) ) ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) [ 0 ] ) . toBe ( li1 ) ;
expect ( element . find ( 'li' ) [ 1 ] ) . toBe ( li0 ) ;
} ) ;
2012-05-08 21:00:38 +00:00
2013-10-05 09:49:09 +00:00
it ( "should throw an exception if 'track by' evaluates to 'hasOwnProperty'" , function ( ) {
scope . items = { age : 20 } ;
$compile ( '<div ng-repeat="(key, value) in items track by \'hasOwnProperty\'"></div>' ) ( scope ) ;
scope . $digest ( ) ;
expect ( $exceptionHandler . errors . shift ( ) . message ) . toMatch ( /ng:badname/ ) ;
} ) ;
2013-03-20 05:27:27 +00:00
it ( 'should track using build in $id function' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="item in items track by $id(item)">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ { name : 'misko' } , { name : 'igor' } ] ;
scope . $digest ( ) ;
var li0 = element . find ( 'li' ) [ 0 ] ;
var li1 = element . find ( 'li' ) [ 1 ] ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items . push ( scope . items . shift ( ) ) ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) [ 0 ] ) . toBe ( li1 ) ;
expect ( element . find ( 'li' ) [ 1 ] ) . toBe ( li0 ) ;
} ) ;
2012-05-08 21:00:38 +00:00
2013-07-18 21:22:04 +00:00
it ( 'should still filter when track is present' , function ( ) {
scope . isIgor = function ( item ) {
return item . name === 'igor' ;
} ;
element = $compile (
'<ul>' +
'<li ng-repeat="item in items | filter:isIgor track by $id(item)">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ { name : 'igor' } , { name : 'misko' } ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . text ( ) ) . toBe ( 'igor;' ) ;
} ) ;
2013-11-18 15:02:55 +00:00
it ( 'should allow expressions over multiple lines' , function ( ) {
scope . isTrue = function ( ) {
return true ;
} ;
element = $compile (
'<ul>' +
'<li ng-repeat="item in items\n' +
'| filter:isTrue">{{item.name}}</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ { name : 'igor' } ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . text ( ) ) . toBe ( 'igor' ) ;
} ) ;
2013-07-18 21:22:04 +00:00
it ( 'should track using provided function when a filter is present' , function ( ) {
scope . newArray = function ( items ) {
var newArray = [ ] ;
angular . forEach ( items , function ( item ) {
newArray . push ( {
id : item . id ,
name : item . name
} ) ;
} ) ;
return newArray ;
} ;
element = $compile (
'<ul>' +
'<li ng-repeat="item in items | filter:newArray track by item.id">{{item.name}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = [
{ id : 1 , name : 'igor' } ,
{ id : 2 , name : 'misko' }
] ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toBe ( 'igor;misko;' ) ;
var li0 = element . find ( 'li' ) [ 0 ] ;
var li1 = element . find ( 'li' ) [ 1 ] ;
scope . items . push ( scope . items . shift ( ) ) ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) [ 0 ] ) . toBe ( li1 ) ;
expect ( element . find ( 'li' ) [ 1 ] ) . toBe ( li0 ) ;
} ) ;
2013-03-20 05:27:27 +00:00
it ( 'should iterate over an array of primitives' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="item in items track by $index">{{item}};</li>' +
'</ul>' ) ( scope ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
Array . prototype . extraProperty = "should be ignored" ;
// INIT
scope . items = [ true , true , true ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'true;true;true;' ) ;
delete Array . prototype . extraProperty ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ false , true , true ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'false;true;true;' ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ false , true , false ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'false;true;false;' ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ true ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 1 ) ;
expect ( element . text ( ) ) . toEqual ( 'true;' ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ true , true , false ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'true;true;false;' ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ true , false , false ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'true;false;false;' ) ;
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
// string
scope . items = [ 'a' , 'a' , 'a' ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'a;a;a;' ) ;
scope . items = [ 'ab' , 'a' , 'a' ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'ab;a;a;' ) ;
2012-03-08 23:00:38 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ 'test' ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 1 ) ;
expect ( element . text ( ) ) . toEqual ( 'test;' ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ 'same' , 'value' ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 2 ) ;
expect ( element . text ( ) ) . toEqual ( 'same;value;' ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
// number
scope . items = [ 12 , 12 , 12 ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( '12;12;12;' ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ 53 , 12 , 27 ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( '53;12;27;' ) ;
scope . items = [ 89 ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 1 ) ;
expect ( element . text ( ) ) . toEqual ( '89;' ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
scope . items = [ 89 , 23 ] ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 2 ) ;
expect ( element . text ( ) ) . toEqual ( '89;23;' ) ;
} ) ;
2012-11-26 19:17:11 +00:00
2012-05-08 21:00:38 +00:00
2013-03-20 05:27:27 +00:00
it ( 'should iterate over object with changing primitive property values' , function ( ) {
// test for issue #933
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
element = $compile (
'<ul>' +
2013-03-20 23:24:23 +00:00
'<li ng-repeat="(key, value) in items track by $index">' +
2013-03-20 05:27:27 +00:00
'{{key}}:{{value}};' +
'<input type="checkbox" ng-model="items[key]">' +
2013-03-20 23:24:23 +00:00
'</li>' +
'</ul>' ) ( scope ) ;
2013-03-20 05:27:27 +00:00
scope . items = { misko : true , shyam : true , zhenbo : true } ;
scope . $digest ( ) ;
expect ( element . find ( 'li' ) . length ) . toEqual ( 3 ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:true;shyam:true;zhenbo:true;' ) ;
2012-11-26 19:17:11 +00:00
2013-03-20 05:27:27 +00:00
browserTrigger ( element . find ( 'input' ) . eq ( 0 ) , 'click' ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:false;shyam:true;zhenbo:true;' ) ;
expect ( element . find ( 'input' ) [ 0 ] . checked ) . toBe ( false ) ;
expect ( element . find ( 'input' ) [ 1 ] . checked ) . toBe ( true ) ;
expect ( element . find ( 'input' ) [ 2 ] . checked ) . toBe ( true ) ;
browserTrigger ( element . find ( 'input' ) . eq ( 0 ) , 'click' ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:true;shyam:true;zhenbo:true;' ) ;
expect ( element . find ( 'input' ) [ 0 ] . checked ) . toBe ( true ) ;
expect ( element . find ( 'input' ) [ 1 ] . checked ) . toBe ( true ) ;
expect ( element . find ( 'input' ) [ 2 ] . checked ) . toBe ( true ) ;
browserTrigger ( element . find ( 'input' ) . eq ( 1 ) , 'click' ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:true;shyam:false;zhenbo:true;' ) ;
expect ( element . find ( 'input' ) [ 0 ] . checked ) . toBe ( true ) ;
expect ( element . find ( 'input' ) [ 1 ] . checked ) . toBe ( false ) ;
expect ( element . find ( 'input' ) [ 2 ] . checked ) . toBe ( true ) ;
scope . items = { misko : false , shyam : true , zhenbo : true } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:false;shyam:true;zhenbo:true;' ) ;
expect ( element . find ( 'input' ) [ 0 ] . checked ) . toBe ( false ) ;
expect ( element . find ( 'input' ) [ 1 ] . checked ) . toBe ( true ) ;
expect ( element . find ( 'input' ) [ 2 ] . checked ) . toBe ( true ) ;
} ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-05-08 21:00:38 +00:00
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should not ngRepeat over parent properties' , function ( ) {
2012-03-08 23:00:38 +00:00
var Class = function ( ) { } ;
Class . prototype . abc = function ( ) { } ;
Class . prototype . value = 'abc' ;
element = $compile (
'<ul>' +
2012-11-23 15:08:47 +00:00
'<li ng-repeat="(key, value) in items">{{key}}:{{value}};</li>' +
'</ul>' ) ( scope ) ;
scope . items = new Class ( ) ;
scope . items . name = 'value' ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toEqual ( 'name:value;' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should error on wrong parsing of ngRepeat' , function ( ) {
2013-03-20 05:27:27 +00:00
element = jqLite ( '<ul><li ng-repeat="i dont parse"></li></ul>' ) ;
$compile ( element ) ( scope ) ;
expect ( $exceptionHandler . errors . shift ( ) [ 0 ] . message ) .
2013-08-13 22:30:52 +00:00
toMatch ( /^\[ngRepeat:iexp\] Expected expression in form of '_item_ in _collection_\[ track by _id_\]' but got 'i dont parse'\./ ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-17 22:57:55 +00:00
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( "should throw error when left-hand-side of ngRepeat can't be parsed" , function ( ) {
element = jqLite ( '<ul><li ng-repeat="i dont parse in foo"></li></ul>' ) ;
$compile ( element ) ( scope ) ;
2013-03-20 05:27:27 +00:00
expect ( $exceptionHandler . errors . shift ( ) [ 0 ] . message ) .
2013-08-13 22:30:52 +00:00
toMatch ( /^\[ngRepeat:iidexp\] '_item_' in '_item_ in _collection_' should be an identifier or '\(_key_, _value_\)' expression, but got 'i dont parse'\./ ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
it ( 'should expose iterator offset as $index when iterating over arrays' ,
2012-11-23 15:08:47 +00:00
function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-11-23 15:08:47 +00:00
'<li ng-repeat="item in items">{{item}}:{{$index}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ 'misko' , 'shyam' , 'frodo' ] ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toEqual ( 'misko:0|shyam:1|frodo:2|' ) ;
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should expose iterator offset as $index when iterating over objects' , function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-11-23 15:08:47 +00:00
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$index}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = { 'misko' : 'm' , 'shyam' : 's' , 'frodo' : 'f' } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toEqual ( 'frodo:f:0|misko:m:1|shyam:s:2|' ) ;
} ) ;
2012-03-08 23:00:38 +00:00
2012-05-02 16:51:31 +00:00
it ( 'should expose iterator position as $first, $middle and $last when iterating over arrays' ,
2012-11-23 15:08:47 +00:00
function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-05-02 16:51:31 +00:00
'<li ng-repeat="item in items">{{item}}:{{$first}}-{{$middle}}-{{$last}}|</li>' +
2012-11-23 15:08:47 +00:00
'</ul>' ) ( scope ) ;
scope . items = [ 'misko' , 'shyam' , 'doug' ] ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) .
toEqual ( 'misko:true-false-false|shyam:false-true-false|doug:false-false-true|' ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
scope . items . push ( 'frodo' ) ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) .
toEqual ( 'misko:true-false-false|' +
'shyam:false-true-false|' +
'doug:false-true-false|' +
'frodo:false-false-true|' ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
scope . items . pop ( ) ;
scope . items . pop ( ) ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko:true-false-false|shyam:false-false-true|' ) ;
2012-11-23 15:08:47 +00:00
scope . items . pop ( ) ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko:true-false-true|' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2013-07-19 15:02:17 +00:00
it ( 'should expose iterator position as $even and $odd when iterating over arrays' ,
function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="item in items">{{item}}:{{$even}}-{{$odd}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = [ 'misko' , 'shyam' , 'doug' ] ;
scope . $digest ( ) ;
expect ( element . text ( ) ) .
toEqual ( 'misko:true-false|shyam:false-true|doug:true-false|' ) ;
scope . items . push ( 'frodo' ) ;
scope . $digest ( ) ;
expect ( element . text ( ) ) .
toBe ( 'misko:true-false|' +
'shyam:false-true|' +
'doug:true-false|' +
'frodo:false-true|' ) ;
scope . items . shift ( ) ;
scope . items . pop ( ) ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toBe ( 'shyam:true-false|doug:false-true|' ) ;
} ) ;
2012-05-02 16:51:31 +00:00
it ( 'should expose iterator position as $first, $middle and $last when iterating over objects' ,
2012-11-23 15:08:47 +00:00
function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-05-02 16:51:31 +00:00
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$first}}-{{$middle}}-{{$last}}|</li>' +
2012-11-23 15:08:47 +00:00
'</ul>' ) ( scope ) ;
scope . items = { 'misko' : 'm' , 'shyam' : 's' , 'doug' : 'd' , 'frodo' : 'f' } ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) .
toEqual ( 'doug:d:true-false-false|' +
'frodo:f:false-true-false|' +
'misko:m:false-true-false|' +
'shyam:s:false-false-true|' ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
delete scope . items . doug ;
delete scope . items . frodo ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko:m:true-false-false|shyam:s:false-false-true|' ) ;
2012-11-23 15:08:47 +00:00
delete scope . items . shyam ;
scope . $digest ( ) ;
2012-05-02 16:51:31 +00:00
expect ( element . text ( ) ) . toEqual ( 'misko:m:true-false-true|' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2013-07-19 15:02:17 +00:00
it ( 'should expose iterator position as $even and $odd when iterating over objects' ,
function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$even}}-{{$odd}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = { 'misko' : 'm' , 'shyam' : 's' , 'doug' : 'd' , 'frodo' : 'f' } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) .
toBe ( 'doug:d:true-false|' +
'frodo:f:false-true|' +
'misko:m:true-false|' +
'shyam:s:false-true|' ) ;
delete scope . items . frodo ;
delete scope . items . shyam ;
scope . $digest ( ) ;
expect ( element . text ( ) ) . toBe ( 'doug:d:true-false|misko:m:false-true|' ) ;
} ) ;
2013-01-11 12:47:38 +00:00
it ( 'should calculate $first, $middle and $last when we filter out properties from an obj' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$first}}-{{$middle}}-{{$last}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = { 'misko' : 'm' , 'shyam' : 's' , 'doug' : 'd' , 'frodo' : 'f' , '$toBeFilteredOut' : 'xxxx' } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) .
toEqual ( 'doug:d:true-false-false|' +
'frodo:f:false-true-false|' +
'misko:m:false-true-false|' +
'shyam:s:false-false-true|' ) ;
} ) ;
2013-07-19 15:02:17 +00:00
it ( 'should calculate $even and $odd when we filter out properties from an obj' , function ( ) {
element = $compile (
'<ul>' +
'<li ng-repeat="(key, val) in items">{{key}}:{{val}}:{{$even}}-{{$odd}}|</li>' +
'</ul>' ) ( scope ) ;
scope . items = { 'misko' : 'm' , 'shyam' : 's' , 'doug' : 'd' , 'frodo' : 'f' , '$toBeFilteredOut' : 'xxxx' } ;
scope . $digest ( ) ;
expect ( element . text ( ) ) .
toEqual ( 'doug:d:true-false|' +
'frodo:f:false-true|' +
'misko:m:true-false|' +
'shyam:s:false-true|' ) ;
} ) ;
2012-11-23 15:08:47 +00:00
it ( 'should ignore $ and $$ properties' , function ( ) {
element = $compile ( '<ul><li ng-repeat="i in items">{{i}}|</li></ul>' ) ( scope ) ;
scope . items = [ 'a' , 'b' , 'c' ] ;
2013-03-20 05:27:27 +00:00
scope . items . $$hashKey = 'xxx' ;
2012-11-23 15:08:47 +00:00
scope . items . $root = 'yyy' ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toEqual ( 'a|b|c|' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should repeat over nested arrays' , function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-03-09 08:00:05 +00:00
'<li ng-repeat="subgroup in groups">' +
'<div ng-repeat="group in subgroup">{{group}}|</div>X' +
2012-03-08 23:00:38 +00:00
'</li>' +
2012-11-23 15:08:47 +00:00
'</ul>' ) ( scope ) ;
scope . groups = [ [ 'a' , 'b' ] , [ 'c' , 'd' ] ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toEqual ( 'a|b|Xc|d|X' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should ignore non-array element properties when iterating over an array' , function ( ) {
element = $compile ( '<ul><li ng-repeat="item in array">{{item}}|</li></ul>' ) ( scope ) ;
scope . array = [ 'a' , 'b' , 'c' ] ;
scope . array . foo = '23' ;
scope . array . bar = function ( ) { } ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toBe ( 'a|b|c|' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should iterate over non-existent elements of a sparse array' , function ( ) {
2013-04-11 23:28:42 +00:00
element = $compile ( '<ul><li ng-repeat="item in array track by $index">{{item}}|</li></ul>' ) ( scope ) ;
2012-11-23 15:08:47 +00:00
scope . array = [ 'a' , 'b' ] ;
scope . array [ 4 ] = 'c' ;
scope . array [ 6 ] = 'd' ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toBe ( 'a|b|||c||d|' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should iterate over all kinds of types' , function ( ) {
element = $compile ( '<ul><li ng-repeat="item in array">{{item}}|</li></ul>' ) ( scope ) ;
scope . array = [ 'a' , 1 , null , undefined , { } ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
expect ( element . text ( ) ) . toMatch ( /a\|1\|\|\|\{\s*\}\|/ ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2013-03-20 23:24:23 +00:00
it ( 'should preserve data on move of elements' , function ( ) {
element = $compile ( '<ul><li ng-repeat="item in array">{{item}}|</li></ul>' ) ( scope ) ;
scope . array = [ 'a' , 'b' ] ;
scope . $digest ( ) ;
var lis = element . find ( 'li' ) ;
lis . eq ( 0 ) . data ( 'mark' , 'a' ) ;
lis . eq ( 1 ) . data ( 'mark' , 'b' ) ;
scope . array = [ 'b' , 'a' ] ;
scope . $digest ( ) ;
2013-06-28 07:28:06 +00:00
lis = element . find ( 'li' ) ;
2013-03-20 23:24:23 +00:00
expect ( lis . eq ( 0 ) . data ( 'mark' ) ) . toEqual ( 'b' ) ;
expect ( lis . eq ( 1 ) . data ( 'mark' ) ) . toEqual ( 'a' ) ;
} ) ;
2013-03-13 23:29:26 +00:00
describe ( 'nesting in replaced directive templates' , function ( ) {
2013-07-03 00:23:51 +00:00
it ( 'should work when placed on a non-root element of attr directive with SYNC replaced template' ,
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'rr' , function ( ) {
return {
restrict : 'A' ,
replace : true ,
template : '<div ng-repeat="i in items">{{i}}|</div>'
} ;
} ) ;
element = jqLite ( '<div><span rr>{{i}}|</span></div>' ) ;
$compile ( element ) ( $rootScope ) ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
$rootScope . items = [ 1 , 2 ] ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '1|2|' ) ;
expect ( sortedHtml ( element ) ) . toBe (
'<div>' +
'<!-- ngRepeat: i in items -->' +
'<div ng-repeat="i in items" rr="">1|</div>' +
2013-09-23 18:24:42 +00:00
'<!-- end ngRepeat: i in items -->' +
2013-07-03 00:23:51 +00:00
'<div ng-repeat="i in items" rr="">2|</div>' +
2013-09-23 18:24:42 +00:00
'<!-- end ngRepeat: i in items -->' +
2013-07-03 00:23:51 +00:00
'</div>'
) ;
} ) ) ;
it ( 'should work when placed on a non-root element of attr directive with ASYNC replaced template' ,
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'rr' , function ( ) {
return {
restrict : 'A' ,
replace : true ,
templateUrl : 'rr.html'
} ;
} ) ;
$templateCache . put ( 'rr.html' , '<div ng-repeat="i in items">{{i}}|</div>' ) ;
element = jqLite ( '<div><span rr>{{i}}|</span></div>' ) ;
$compile ( element ) ( $rootScope ) ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
$rootScope . items = [ 1 , 2 ] ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '1|2|' ) ;
expect ( sortedHtml ( element ) ) . toBe (
'<div>' +
'<!-- ngRepeat: i in items -->' +
'<div ng-repeat="i in items" rr="">1|</div>' +
2013-09-23 18:24:42 +00:00
'<!-- end ngRepeat: i in items -->' +
2013-07-03 00:23:51 +00:00
'<div ng-repeat="i in items" rr="">2|</div>' +
2013-09-23 18:24:42 +00:00
'<!-- end ngRepeat: i in items -->' +
2013-07-03 00:23:51 +00:00
'</div>'
) ;
} ) ) ;
2013-03-13 23:29:26 +00:00
it ( 'should work when placed on a root element of attr directive with SYNC replaced template' ,
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'replaceMeWithRepeater' , function ( ) {
return {
replace : true ,
template : '<span ng-repeat="i in items">{{log(i)}}</span>'
2013-06-28 07:28:06 +00:00
} ;
2013-03-13 23:29:26 +00:00
} ) ;
element = jqLite ( '<span replace-me-with-repeater></span>' ) ;
$compile ( element ) ( $rootScope ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
var logs = [ ] ;
$rootScope . log = function ( t ) { logs . push ( t ) ; } ;
// This creates one item, but it has no parent so we can't get to it
$rootScope . items = [ 1 , 2 ] ;
$rootScope . $apply ( ) ;
// This cleans up to prevent memory leak
$rootScope . items = [ ] ;
$rootScope . $apply ( ) ;
expect ( angular . mock . dump ( element ) ) . toBe ( '<!-- ngRepeat: i in items -->' ) ;
expect ( logs ) . toEqual ( [ 1 , 2 , 1 , 2 ] ) ;
} ) ) ;
2013-06-28 07:28:06 +00:00
it ( 'should work when placed on a root element of attr directive with ASYNC replaced template' ,
2013-03-13 23:29:26 +00:00
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'replaceMeWithRepeater' , function ( ) {
return {
replace : true ,
templateUrl : 'replace-me-with-repeater.html'
2013-06-28 07:28:06 +00:00
} ;
2013-03-13 23:29:26 +00:00
} ) ;
$templateCache . put ( 'replace-me-with-repeater.html' , '<div ng-repeat="i in items">{{log(i)}}</div>' ) ;
element = jqLite ( '<span>-</span><span replace-me-with-repeater></span><span>-</span>' ) ;
$compile ( element ) ( $rootScope ) ;
expect ( element . text ( ) ) . toBe ( '--' ) ;
var logs = [ ] ;
$rootScope . log = function ( t ) { logs . push ( t ) ; } ;
// This creates one item, but it has no parent so we can't get to it
$rootScope . items = [ 1 , 2 ] ;
$rootScope . $apply ( ) ;
// This cleans up to prevent memory leak
$rootScope . items = [ ] ;
$rootScope . $apply ( ) ;
expect ( sortedHtml ( element ) ) . toBe ( '<span>-</span><!-- ngRepeat: i in items --><span>-</span>' ) ;
expect ( logs ) . toEqual ( [ 1 , 2 , 1 , 2 ] ) ;
} ) ) ;
it ( 'should work when placed on a root element of element directive with SYNC replaced template' ,
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'replaceMeWithRepeater' , function ( ) {
return {
restrict : 'E' ,
replace : true ,
template : '<div ng-repeat="i in [1,2,3]">{{i}}</div>'
2013-06-28 07:28:06 +00:00
} ;
2013-03-13 23:29:26 +00:00
} ) ;
element = $compile ( '<div><replace-me-with-repeater></replace-me-with-repeater></div>' ) ( $rootScope ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '123' ) ;
} ) ) ;
2013-07-02 18:11:52 +00:00
if ( ! msie || msie > 8 ) {
// only IE>8 supports element directives
it ( 'should work when placed on a root element of element directive with ASYNC replaced template' ,
inject ( function ( $templateCache , $compile , $rootScope ) {
$compileProvider . directive ( 'replaceMeWithRepeater' , function ( ) {
return {
restrict : 'E' ,
replace : true ,
templateUrl : 'replace-me-with-repeater.html'
} ;
} ) ;
$templateCache . put ( 'replace-me-with-repeater.html' , '<div ng-repeat="i in [1,2,3]">{{i}}</div>' ) ;
element = $compile ( '<div><replace-me-with-repeater></replace-me-with-repeater></div>' ) ( $rootScope ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '123' ) ;
} ) ) ;
}
2013-03-13 23:29:26 +00:00
2013-11-27 03:55:02 +00:00
it ( 'should work when combined with an ASYNC template that loads after the first digest' , inject ( function ( $httpBackend , $compile , $rootScope ) {
$compileProvider . directive ( 'test' , function ( ) {
return {
templateUrl : 'test.html'
} ;
} ) ;
$httpBackend . whenGET ( 'test.html' ) . respond ( 'hello' ) ;
element = jqLite ( '<div><div ng-repeat="i in items" test></div></div>' ) ;
$compile ( element ) ( $rootScope ) ;
$rootScope . items = [ 1 ] ;
$rootScope . $apply ( ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
$httpBackend . flush ( ) ;
expect ( element . text ( ) ) . toBe ( 'hello' ) ;
$rootScope . items = [ ] ;
$rootScope . $apply ( ) ;
// Note: there are still comments in element!
expect ( element . children ( ) . length ) . toBe ( 0 ) ;
expect ( element . text ( ) ) . toBe ( '' ) ;
} ) ) ;
} ) ;
2013-03-13 23:29:26 +00:00
2013-09-23 18:24:42 +00:00
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'
] ) ;
} ) ) ;
2012-03-08 23:00:38 +00:00
describe ( 'stability' , function ( ) {
var a , b , c , d , lis ;
2012-11-23 15:08:47 +00:00
beforeEach ( function ( ) {
2012-03-08 23:00:38 +00:00
element = $compile (
'<ul>' +
2012-05-02 16:51:31 +00:00
'<li ng-repeat="item in items">{{key}}:{{val}}|></li>' +
2012-11-23 15:08:47 +00:00
'</ul>' ) ( scope ) ;
2012-03-08 23:00:38 +00:00
a = { } ;
b = { } ;
c = { } ;
d = { } ;
2012-11-23 15:08:47 +00:00
scope . items = [ a , b , c ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
lis = element . find ( 'li' ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should preserve the order of elements' , function ( ) {
scope . items = [ a , c , d ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
var newElements = element . find ( 'li' ) ;
expect ( newElements [ 0 ] ) . toEqual ( lis [ 0 ] ) ;
expect ( newElements [ 1 ] ) . toEqual ( lis [ 2 ] ) ;
expect ( newElements [ 2 ] ) . not . toEqual ( lis [ 1 ] ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2013-04-11 23:28:42 +00:00
it ( 'should throw error on adding existing duplicates and recover' , function ( ) {
2013-03-20 05:27:27 +00:00
scope . items = [ a , a , a ] ;
2012-11-23 15:08:47 +00:00
scope . $digest ( ) ;
2013-03-20 05:27:27 +00:00
expect ( $exceptionHandler . errors . shift ( ) . message ) .
2013-08-13 22:30:52 +00:00
toMatch ( /^\[ngRepeat:dupes\] Duplicates in a repeater are not allowed\. Use 'track by' expression to specify unique keys\. Repeater: item in items, Duplicate key: object:003/ ) ;
2013-04-11 23:28:42 +00:00
// recover
scope . items = [ a ] ;
scope . $digest ( ) ;
var newElements = element . find ( 'li' ) ;
expect ( newElements . length ) . toEqual ( 1 ) ;
expect ( newElements [ 0 ] ) . toEqual ( lis [ 0 ] ) ;
scope . items = [ ] ;
scope . $digest ( ) ;
2013-06-28 07:28:06 +00:00
newElements = element . find ( 'li' ) ;
2013-04-11 23:28:42 +00:00
expect ( newElements . length ) . toEqual ( 0 ) ;
} ) ;
it ( 'should throw error on new duplicates and recover' , function ( ) {
scope . items = [ d , d , d ] ;
scope . $digest ( ) ;
expect ( $exceptionHandler . errors . shift ( ) . message ) .
2013-08-13 22:30:52 +00:00
toMatch ( /^\[ngRepeat:dupes\] Duplicates in a repeater are not allowed\. Use 'track by' expression to specify unique keys\. Repeater: item in items, Duplicate key: object:009/ ) ;
2012-03-08 23:00:38 +00:00
2013-03-20 05:27:27 +00:00
// recover
scope . items = [ a ] ;
2012-11-23 15:08:47 +00:00
scope . $digest ( ) ;
2013-03-20 05:27:27 +00:00
var newElements = element . find ( 'li' ) ;
expect ( newElements . length ) . toEqual ( 1 ) ;
2012-03-08 23:00:38 +00:00
expect ( newElements [ 0 ] ) . toEqual ( lis [ 0 ] ) ;
2013-03-20 05:27:27 +00:00
scope . items = [ ] ;
2012-11-23 15:08:47 +00:00
scope . $digest ( ) ;
2013-06-28 07:28:06 +00:00
newElements = element . find ( 'li' ) ;
2013-03-20 05:27:27 +00:00
expect ( newElements . length ) . toEqual ( 0 ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-03-08 23:00:38 +00:00
2012-11-23 15:08:47 +00:00
it ( 'should reverse items when the collection is reversed' , function ( ) {
scope . items = [ a , b , c ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
lis = element . find ( 'li' ) ;
2012-11-23 15:08:47 +00:00
scope . items = [ c , b , a ] ;
scope . $digest ( ) ;
2012-03-08 23:00:38 +00:00
var newElements = element . find ( 'li' ) ;
expect ( newElements . length ) . toEqual ( 3 ) ;
expect ( newElements [ 0 ] ) . toEqual ( lis [ 2 ] ) ;
expect ( newElements [ 1 ] ) . toEqual ( lis [ 1 ] ) ;
expect ( newElements [ 2 ] ) . toEqual ( lis [ 0 ] ) ;
2012-11-23 15:08:47 +00:00
} ) ;
2012-11-23 21:43:30 +00:00
it ( 'should reuse elements even when model is composed of primitives' , function ( ) {
// rebuilding repeater from scratch can be expensive, we should try to avoid it even for
// model that is composed of primitives.
scope . items = [ 'hello' , 'cau' , 'ahoj' ] ;
scope . $digest ( ) ;
lis = element . find ( 'li' ) ;
2013-03-20 23:24:23 +00:00
lis [ 2 ] . id = 'yes' ;
2012-11-23 21:43:30 +00:00
scope . items = [ 'ahoj' , 'hello' , 'cau' ] ;
scope . $digest ( ) ;
var newLis = element . find ( 'li' ) ;
expect ( newLis . length ) . toEqual ( 3 ) ;
expect ( newLis [ 0 ] ) . toEqual ( lis [ 2 ] ) ;
expect ( newLis [ 1 ] ) . toEqual ( lis [ 0 ] ) ;
expect ( newLis [ 2 ] ) . toEqual ( lis [ 1 ] ) ;
} ) ;
2013-09-24 20:51:28 +00:00
it ( 'should be stable even if the collection is initially undefined' , function ( ) {
scope . items = undefined ;
scope . $digest ( ) ;
scope . items = [
{ name : 'A' } ,
{ name : 'B' } ,
{ name : 'C' }
] ;
scope . $digest ( ) ;
lis = element . find ( 'li' ) ;
scope . items . shift ( ) ;
scope . $digest ( ) ;
var newLis = element . find ( 'li' ) ;
expect ( newLis . length ) . toBe ( 2 ) ;
expect ( newLis [ 0 ] ) . toBe ( lis [ 1 ] ) ;
} ) ;
2012-03-08 23:00:38 +00:00
} ) ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
2013-09-23 18:24:42 +00:00
2013-10-11 04:35:54 +00:00
describe ( 'compatibility' , function ( ) {
it ( 'should allow mixing ngRepeat and another element transclusion directive' , function ( ) {
$compileProvider . directive ( 'elmTrans' , valueFn ( {
transclude : 'element' ,
controller : function ( $transclude , $scope , $element ) {
$transclude ( function ( transcludedNodes ) {
$element . after ( ']]' ) . after ( transcludedNodes ) . after ( '[[' ) ;
} ) ;
}
} ) ) ;
inject ( function ( $compile , $rootScope ) {
element = $compile ( '<div><div ng-repeat="i in [1,2]" elm-trans>{{i}}</div></div>' ) ( $rootScope ) ;
$rootScope . $digest ( ) ;
expect ( element . text ( ) ) . toBe ( '[[1]][[2]]' )
} ) ;
} ) ;
it ( 'should allow mixing ngRepeat with ngInclude' , inject ( function ( $compile , $rootScope , $httpBackend ) {
$httpBackend . whenGET ( 'someTemplate.html' ) . respond ( '<p>some template; </p>' ) ;
element = $compile ( '<div><div ng-repeat="i in [1,2]" ng-include="\'someTemplate.html\'"></div></div>' ) ( $rootScope ) ;
$rootScope . $digest ( ) ;
$httpBackend . flush ( ) ;
expect ( element . text ( ) ) . toBe ( 'some template; some template; ' ) ;
} ) ) ;
it ( 'should allow mixing ngRepeat with ngIf' , inject ( function ( $compile , $rootScope ) {
element = $compile ( '<div><div ng-repeat="i in [1,2,3,4]" ng-if="i % 2 == 0">{{i}};</div></div>' ) ( $rootScope ) ;
$rootScope . $digest ( ) ;
expect ( element . text ( ) ) . toBe ( '2;4;' ) ;
} ) ) ;
} ) ;
2013-09-23 18:24:42 +00:00
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 (
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
'<div>' +
2013-09-23 18:24:42 +00:00
'<div ng-repeat-start="val in values">val:{{val}};</div>' +
'<div ng-if="showMe" ng-repeat-end>if:{{val}};</div>' +
'</div>'
) ( $rootScope ) ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
2013-09-23 18:24:42 +00:00
$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;' ) ;
} ) ) ;
} ) ;
2012-03-08 23:00:38 +00:00
} ) ;
2013-03-20 23:24:23 +00:00
2013-11-14 21:50:36 +00:00
describe ( 'ngRepeat and transcludes' , function ( ) {
it ( 'should allow access to directive controller from children when used in a replace template' , function ( ) {
var controller ;
module ( function ( $compileProvider ) {
var directive = $compileProvider . directive ;
directive ( 'template' , valueFn ( {
template : '<div ng-repeat="l in [1]"><span test></span></div>' ,
replace : true ,
controller : function ( ) {
this . flag = true ;
}
} ) ) ;
directive ( 'test' , valueFn ( {
require : '^template' ,
link : function ( scope , el , attr , ctrl ) {
controller = ctrl ;
}
} ) ) ;
} ) ;
inject ( function ( $compile , $rootScope ) {
var element = $compile ( '<div><div template></div></div>' ) ( $rootScope ) ;
$rootScope . $apply ( ) ;
expect ( controller . flag ) . toBe ( true ) ;
dealoc ( element ) ;
} ) ;
} ) ;
} ) ;
2013-09-23 18:24:42 +00:00
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
describe ( 'ngRepeat animations' , function ( ) {
2013-06-18 02:40:01 +00:00
var body , element , $rootElement ;
2013-04-09 22:33:16 +00:00
function html ( html ) {
2013-06-18 02:40:01 +00:00
$rootElement . html ( html ) ;
element = $rootElement . children ( ) . eq ( 0 ) ;
2013-04-09 22:33:16 +00:00
return element ;
}
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
beforeEach ( module ( 'mock.animate' ) ) ;
2013-04-23 11:34:53 +00:00
2013-06-18 02:40:01 +00:00
beforeEach ( module ( function ( ) {
2013-04-09 22:33:16 +00:00
// we need to run animation on attached elements;
2013-06-18 02:40:01 +00:00
return function ( _$rootElement _ ) {
$rootElement = _$rootElement _ ;
body = jqLite ( document . body ) ;
body . append ( $rootElement ) ;
} ;
} ) ) ;
2013-04-09 22:33:16 +00:00
afterEach ( function ( ) {
dealoc ( body ) ;
dealoc ( element ) ;
} ) ;
2013-03-20 23:24:23 +00:00
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
it ( 'should fire off the enter animation' ,
inject ( function ( $compile , $rootScope , $animate ) {
2013-03-20 23:24:23 +00:00
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
var item ;
2013-03-20 23:24:23 +00:00
2013-04-09 22:33:16 +00:00
element = $compile ( html (
2013-03-20 23:24:23 +00:00
'<div><div ' +
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
'ng-repeat="item in items">' +
2013-05-24 18:00:14 +00:00
'{{ item }}' +
2013-03-20 23:24:23 +00:00
'</div></div>'
2013-04-09 22:33:16 +00:00
) ) ( $rootScope ) ;
$rootScope . $digest ( ) ; // re-enable the animations;
2013-03-20 23:24:23 +00:00
$rootScope . items = [ '1' , '2' , '3' ] ;
$rootScope . $digest ( ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '1' ) ;
2013-03-20 23:24:23 +00:00
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '2' ) ;
2013-03-20 23:24:23 +00:00
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '3' ) ;
2013-03-20 23:24:23 +00:00
} ) ) ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
it ( 'should fire off the leave animation' ,
inject ( function ( $compile , $rootScope , $animate ) {
var item ;
2013-03-20 23:24:23 +00:00
2013-04-09 22:33:16 +00:00
element = $compile ( html (
2013-03-20 23:24:23 +00:00
'<div><div ' +
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
'ng-repeat="item in items">' +
2013-05-24 18:00:14 +00:00
'{{ item }}' +
2013-03-20 23:24:23 +00:00
'</div></div>'
2013-04-09 22:33:16 +00:00
) ) ( $rootScope ) ;
2013-03-20 23:24:23 +00:00
$rootScope . items = [ '1' , '2' , '3' ] ;
$rootScope . $digest ( ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '1' ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '2' ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '3' ) ;
2013-03-20 23:24:23 +00:00
$rootScope . items = [ '1' , '3' ] ;
$rootScope . $digest ( ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'leave' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '2' ) ;
2013-03-20 23:24:23 +00:00
} ) ) ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
it ( 'should fire off the move animation' ,
inject ( function ( $compile , $rootScope , $animate ) {
var item ;
2013-04-09 22:33:16 +00:00
element = $compile ( html (
2013-03-20 23:24:23 +00:00
'<div>' +
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
'<div ng-repeat="item in items">' +
2013-03-20 23:24:23 +00:00
'{{ item }}' +
'</div>' +
'</div>'
2013-04-09 22:33:16 +00:00
) ) ( $rootScope ) ;
2013-03-20 23:24:23 +00:00
$rootScope . items = [ '1' , '2' , '3' ] ;
$rootScope . $digest ( ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '1' ) ;
2013-03-20 23:24:23 +00:00
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '2' ) ;
2013-03-20 23:24:23 +00:00
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'enter' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '3' ) ;
2013-03-20 23:24:23 +00:00
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
$rootScope . items = [ '2' , '3' , '1' ] ;
2013-03-20 23:24:23 +00:00
$rootScope . $digest ( ) ;
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'move' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '2' ) ;
2013-03-20 23:24:23 +00:00
2013-07-31 19:38:19 +00:00
item = $animate . flushNext ( 'move' ) . element ;
feat(ngAnimate): complete rewrite of animations
- ngAnimate directive is gone and was replaced with class based animations/transitions
- support for triggering animations on css class additions and removals
- done callback was added to all animation apis
- $animation and $animator where merged into a single $animate service with api:
- $animate.enter(element, parent, after, done);
- $animate.leave(element, done);
- $animate.move(element, parent, after, done);
- $animate.addClass(element, className, done);
- $animate.removeClass(element, className, done);
BREAKING CHANGE: too many things changed, we'll write up a separate doc with migration instructions
2013-06-18 17:59:57 +00:00
expect ( item . text ( ) ) . toBe ( '1' ) ;
2013-06-11 20:14:17 +00:00
} ) ) ;
2013-03-20 23:24:23 +00:00
} ) ;