From 0b6f1ce5f89f47f9302ff1e8cd8f4b92f837c413 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Wed, 20 Mar 2013 16:24:23 -0700 Subject: feat(ngAnimate): add support for animation --- test/ng/directive/ngIncludeSpec.js | 113 +++++++++++++++++++ test/ng/directive/ngRepeatSpec.js | 211 +++++++++++++++++++++++++++++++++++- test/ng/directive/ngShowHideSpec.js | 101 +++++++++++++++++ test/ng/directive/ngSwitchSpec.js | 118 ++++++++++++++++++++ test/ng/directive/ngViewSpec.js | 104 +++++++++++++++++- 5 files changed, 643 insertions(+), 4 deletions(-) (limited to 'test/ng/directive') diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js index dce803b5..191eaa05 100644 --- a/test/ng/directive/ngIncludeSpec.js +++ b/test/ng/directive/ngIncludeSpec.js @@ -280,3 +280,116 @@ describe('ngInclude', function() { })); }); }); + +describe('ngInclude ngAnimate', function() { + var element, vendorPrefix, window; + + beforeEach(module(function($animationProvider, $provide) { + $provide.value('$window', window = angular.mock.createMockWindow()); + return function($sniffer) { + vendorPrefix = '-' + $sniffer.vendorPrefix + '-'; + }; + })); + + afterEach(function(){ + dealoc(element); + }); + + it('should fire off the enter animation + add and remove the css classes', + inject(function($compile, $rootScope, $templateCache, $sniffer) { + + $templateCache.put('enter', [200, '
data
', {}]); + $rootScope.tpl = 'enter'; + element = $compile( + '
' + + '
' + )($rootScope); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = vendorPrefix + 'transition'; + var cssValue = '1s linear all'; + child.css(cssProp, cssValue); + + if ($sniffer.supportsTransitions) { + expect(child.attr('class')).toContain('custom-enter-setup'); + window.setTimeout.expect(1).process(); + + expect(child.attr('class')).toContain('custom-enter-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(child.attr('class')).not.toContain('custom-enter-setup'); + expect(child.attr('class')).not.toContain('custom-enter-start'); + })); + + it('should fire off the leave animation + add and remove the css classes', + inject(function($compile, $rootScope, $templateCache, $sniffer) { + $templateCache.put('enter', [200, '
data
', {}]); + $rootScope.tpl = 'enter'; + element = $compile( + '
' + + '
' + )($rootScope); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = vendorPrefix + 'transition'; + var cssValue = '1s linear all'; + child.css(cssProp, cssValue); + + $rootScope.tpl = ''; + $rootScope.$digest(); + + if ($sniffer.supportsTransitions) { + expect(child.attr('class')).toContain('custom-leave-setup'); + window.setTimeout.expect(1).process(); + + expect(child.attr('class')).toContain('custom-leave-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(child.attr('class')).not.toContain('custom-leave-setup'); + expect(child.attr('class')).not.toContain('custom-leave-start'); + })); + + it('should catch and use the correct duration for animation', + inject(function($compile, $rootScope, $templateCache, $sniffer) { + $templateCache.put('enter', [200, '
data
', {}]); + $rootScope.tpl = 'enter'; + element = $compile( + '
' + + '
' + )($rootScope); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = vendorPrefix + 'transition'; + var cssValue = '0.5s linear all'; + child.css(cssProp, cssValue); + + $rootScope.tpl = 'enter'; + $rootScope.$digest(); + + if ($sniffer.supportsTransitions) { + window.setTimeout.expect(1).process(); + window.setTimeout.expect(500).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + })); + +}); diff --git a/test/ng/directive/ngRepeatSpec.js b/test/ng/directive/ngRepeatSpec.js index 44406d6d..533b83c8 100644 --- a/test/ng/directive/ngRepeatSpec.js +++ b/test/ng/directive/ngRepeatSpec.js @@ -189,11 +189,11 @@ describe('ngRepeat', function() { element = $compile( '')(scope); + '' + + '')(scope); scope.items = {misko: true, shyam: true, zhenbo:true}; scope.$digest(); @@ -410,6 +410,24 @@ describe('ngRepeat', function() { }); + it('should preserve data on move of elements', function() { + element = $compile('')(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(); + + var lis = element.find('li'); + expect(lis.eq(0).data('mark')).toEqual('b'); + expect(lis.eq(1).data('mark')).toEqual('a'); + }); + + describe('stability', function() { var a, b, c, d, lis; @@ -481,6 +499,7 @@ describe('ngRepeat', function() { scope.items = ['hello', 'cau', 'ahoj']; scope.$digest(); lis = element.find('li'); + lis[2].id = 'yes'; scope.items = ['ahoj', 'hello', 'cau']; scope.$digest(); @@ -492,3 +511,189 @@ describe('ngRepeat', function() { }); }); }); + +describe('ngRepeat ngAnimate', function() { + var element, vendorPrefix, window; + + beforeEach(module(function($animationProvider, $provide) { + $provide.value('$window', window = angular.mock.createMockWindow()); + return function($sniffer) { + vendorPrefix = '-' + $sniffer.vendorPrefix + '-'; + }; + })); + + afterEach(function(){ + dealoc(element); + }); + + it('should fire off the enter animation + add and remove the css classes', + inject(function($compile, $rootScope, $sniffer) { + + element = $compile( + '
' + + '{{ item }}' + + '
' + )($rootScope); + + $rootScope.items = ['1','2','3']; + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var cssProp = vendorPrefix + 'transition'; + var cssValue = '1s linear all'; + var kids = element.children(); + for(var i=0;i
' + + '{{ item }}' + + '
' + )($rootScope); + + $rootScope.items = ['1','2','3']; + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var cssProp = vendorPrefix + 'transition'; + var cssValue = '1s linear all'; + var kids = element.children(); + for(var i=0;i' + + '
' + + '{{ item }}' + + '
' + + '' + )($rootScope); + + $rootScope.items = ['1','2','3']; + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var cssProp = '-' + $sniffer.vendorPrefix + '-transition'; + var cssValue = '1s linear all'; + var kids = element.children(); + for(var i=0;i
' + + '{{ item }}' + + '
' + )($rootScope); + + $rootScope.items = ['a','b']; + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var kids = element.children(); + var first = jqLite(kids[0]); + var second = jqLite(kids[1]); + var cssProp = '-' + $sniffer.vendorPrefix + '-transition'; + var cssValue = '0.5s linear all'; + first.css(cssProp, cssValue); + second.css(cssProp, cssValue); + + if ($sniffer.supportsTransitions) { + window.setTimeout.expect(1).process(); + window.setTimeout.expect(1).process(); + window.setTimeout.expect(500).process(); + window.setTimeout.expect(500).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + })); + +}); diff --git a/test/ng/directive/ngShowHideSpec.js b/test/ng/directive/ngShowHideSpec.js index ee251dbf..d1d314e7 100644 --- a/test/ng/directive/ngShowHideSpec.js +++ b/test/ng/directive/ngShowHideSpec.js @@ -41,3 +41,104 @@ describe('ngShow / ngHide', function() { })); }); }); + +describe('ngShow / ngHide - ngAnimate', function() { + var element, window; + var vendorPrefix; + + beforeEach(module(function($animationProvider, $provide) { + $provide.value('$window', window = angular.mock.createMockWindow()); + return function($sniffer) { + vendorPrefix = '-' + $sniffer.vendorPrefix + '-'; + }; + })); + + afterEach(function() { + dealoc(element); + }); + + describe('ngShow', function() { + it('should fire off the animator.show and animator.hide animation', inject(function($compile, $rootScope, $sniffer) { + var $scope = $rootScope.$new(); + $scope.on = true; + element = $compile( + '
' + + '
' + )($scope); + $scope.$digest(); + + if ($sniffer.supportsTransitions) { + expect(element.attr('class')).toContain('custom-show-setup'); + window.setTimeout.expect(1).process(); + + expect(element.attr('class')).toContain('custom-show-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(element.attr('class')).not.toContain('custom-show-start'); + expect(element.attr('class')).not.toContain('custom-show-setup'); + + $scope.on = false; + $scope.$digest(); + if ($sniffer.supportsTransitions) { + expect(element.attr('class')).toContain('custom-hide-setup'); + window.setTimeout.expect(1).process(); + expect(element.attr('class')).toContain('custom-hide-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(element.attr('class')).not.toContain('custom-hide-start'); + expect(element.attr('class')).not.toContain('custom-hide-setup'); + })); + }); + + describe('ngHide', function() { + it('should fire off the animator.show and animator.hide animation', inject(function($compile, $rootScope, $sniffer) { + var $scope = $rootScope.$new(); + $scope.off = true; + element = $compile( + '
' + + '
' + )($scope); + $scope.$digest(); + + if ($sniffer.supportsTransitions) { + expect(element.attr('class')).toContain('custom-hide-setup'); + window.setTimeout.expect(1).process(); + + expect(element.attr('class')).toContain('custom-hide-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(element.attr('class')).not.toContain('custom-hide-start'); + expect(element.attr('class')).not.toContain('custom-hide-setup'); + + $scope.off = false; + $scope.$digest(); + + if ($sniffer.supportsTransitions) { + expect(element.attr('class')).toContain('custom-show-setup'); + window.setTimeout.expect(1).process(); + expect(element.attr('class')).toContain('custom-show-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(element.attr('class')).not.toContain('custom-show-start'); + expect(element.attr('class')).not.toContain('custom-show-setup'); + })); + }); +}); diff --git a/test/ng/directive/ngSwitchSpec.js b/test/ng/directive/ngSwitchSpec.js index 85240b19..9d3eceaa 100644 --- a/test/ng/directive/ngSwitchSpec.js +++ b/test/ng/directive/ngSwitchSpec.js @@ -213,3 +213,121 @@ describe('ngSwitch', function() { // afterwards a global afterEach will check for leaks in jq data cache object })); }); + +describe('ngSwitch ngAnimate', function() { + var element, vendorPrefix, window; + + beforeEach(module(function($animationProvider, $provide) { + $provide.value('$window', window = angular.mock.createMockWindow()); + return function($sniffer) { + vendorPrefix = '-' + $sniffer.vendorPrefix + '-'; + }; + })); + + afterEach(function(){ + dealoc(element); + }); + + it('should fire off the enter animation + set and remove the classes', + inject(function($compile, $rootScope, $sniffer) { + var $scope = $rootScope.$new(); + var style = vendorPrefix + 'transition: 1s linear all'; + element = $compile( + '
' + + '
one
' + + '
two
' + + '
three
' + + '
' + )($scope); + + $scope.val = 'one'; + $scope.$digest(); + + expect(element.children().length).toBe(1); + var first = element.children()[0]; + + if ($sniffer.supportsTransitions) { + expect(first.className).toContain('cool-enter-setup'); + window.setTimeout.expect(1).process(); + + expect(first.className).toContain('cool-enter-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(first.className).not.toContain('cool-enter-setup'); + expect(first.className).not.toContain('cool-enter-start'); + })); + + + it('should fire off the leave animation + set and remove the classes', + inject(function($compile, $rootScope, $sniffer) { + var $scope = $rootScope.$new(); + var style = vendorPrefix + 'transition: 1s linear all'; + element = $compile( + '
' + + '
one
' + + '
two
' + + '
three
' + + '
' + )($scope); + + $scope.val = 'two'; + $scope.$digest(); + + if ($sniffer.supportsTransitions) { + window.setTimeout.expect(1).process(); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + $scope.val = 'three'; + $scope.$digest(); + + expect(element.children().length).toBe($sniffer.supportsTransitions ? 2 : 1); + var first = element.children()[0]; + + + if ($sniffer.supportsTransitions) { + expect(first.className).toContain('cool-leave-setup'); + window.setTimeout.expect(1).process(); + window.setTimeout.expect(1).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + + if ($sniffer.supportsTransitions) { + expect(first.className).toContain('cool-leave-start'); + window.setTimeout.expect(1000).process(); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(first.className).not.toContain('cool-leave-setup'); + expect(first.className).not.toContain('cool-leave-start'); + })); + + it('should catch and use the correct duration for animation', + inject(function($compile, $rootScope, $sniffer) { + element = $compile( + '
' + + '
one
' + + '
' + )($rootScope); + + $rootScope.val = 'one'; + $rootScope.$digest(); + + if ($sniffer.supportsTransitions) { + window.setTimeout.expect(1).process(); + window.setTimeout.expect(500).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + })); + +}); diff --git a/test/ng/directive/ngViewSpec.js b/test/ng/directive/ngViewSpec.js index e781b98b..dcdfe686 100644 --- a/test/ng/directive/ngViewSpec.js +++ b/test/ng/directive/ngViewSpec.js @@ -473,7 +473,7 @@ describe('ngView', function() { $rootScope.$digest(); forEach(element.contents(), function(node) { - if ( node.nodeType == 3 ) { + if ( node.nodeType == 3 /* text node */) { expect(jqLite(node).scope()).not.toBe($route.current.scope); expect(jqLite(node).controller()).not.toBeDefined(); } else { @@ -484,3 +484,105 @@ describe('ngView', function() { }); }); }); + +describe('ngAnimate', function() { + var element, window; + + beforeEach(module(function($provide, $routeProvider) { + $provide.value('$window', window = angular.mock.createMockWindow()); + $routeProvider.when('/foo', {controller: noop, templateUrl: '/foo.html'}); + return function($templateCache) { + $templateCache.put('/foo.html', [200, '
data
', {}]); + } + })); + + afterEach(function(){ + dealoc(element); + }); + + it('should fire off the enter animation + add and remove the css classes', + inject(function($compile, $rootScope, $sniffer, $location, $templateCache) { + element = $compile('
')($rootScope); + + $location.path('/foo'); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = '-' + $sniffer.vendorPrefix + '-transition'; + var cssValue = '1s linear all'; + child.css(cssProp, cssValue); + + if ($sniffer.supportsTransitions) { + expect(child.attr('class')).toContain('custom-enter-setup'); + window.setTimeout.expect(1).process(); + + expect(child.attr('class')).toContain('custom-enter-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(child.attr('class')).not.toContain('custom-enter-setup'); + expect(child.attr('class')).not.toContain('custom-enter-start'); + })); + + it('should fire off the leave animation + add and remove the css classes', + inject(function($compile, $rootScope, $sniffer, $location, $templateCache) { + $templateCache.put('/foo.html', [200, '
foo
', {}]); + element = $compile('
')($rootScope); + + $location.path('/foo'); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = '-' + $sniffer.vendorPrefix + '-transition'; + var cssValue = '1s linear all'; + child.css(cssProp, cssValue); + + $location.path('/'); + $rootScope.$digest(); + + if ($sniffer.supportsTransitions) { + expect(child.attr('class')).toContain('custom-leave-setup'); + window.setTimeout.expect(1).process(); + + expect(child.attr('class')).toContain('custom-leave-start'); + window.setTimeout.expect(1000).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + + expect(child.attr('class')).not.toContain('custom-leave-setup'); + expect(child.attr('class')).not.toContain('custom-leave-start'); + })); + + it('should catch and use the correct duration for animations', + inject(function($compile, $rootScope, $sniffer, $location, $templateCache) { + $templateCache.put('/foo.html', [200, '
foo
', {}]); + element = $compile( + '
' + + '
' + )($rootScope); + + $location.path('/foo'); + $rootScope.$digest(); + + //if we add the custom css stuff here then it will get picked up before the animation takes place + var child = jqLite(element.children()[0]); + var cssProp = '-' + $sniffer.vendorPrefix + '-transition'; + var cssValue = '0.5s linear all'; + child.css(cssProp, cssValue); + + if($sniffer.supportsTransitions) { + window.setTimeout.expect(1).process(); + window.setTimeout.expect($sniffer.supportsTransitions ? 500 : 0).process(); + } else { + expect(window.setTimeout.queue).toEqual([]); + } + })); + +}); -- cgit v1.2.3