From 33443966c8e8cac85a863bb181d4a4aff00baab4 Mon Sep 17 00:00:00 2001 From: Yves Brissaud Date: Tue, 10 Dec 2013 21:49:31 +0100 Subject: feat($animate): animate dirty, pristine, valid, invalid for form/fields Add css animations when form or field status change to/from dirty, pristine, valid or invalid. This works like animation system present with ngClass, ngShow, etc. Closes #5378 --- test/ng/directive/formSpec.js | 80 ++++++++++++++++++++++++++++++++++ test/ng/directive/inputSpec.js | 98 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) (limited to 'test') diff --git a/test/ng/directive/formSpec.js b/test/ng/directive/formSpec.js index dde6f0a0..b55d1f8d 100644 --- a/test/ng/directive/formSpec.js +++ b/test/ng/directive/formSpec.js @@ -594,3 +594,83 @@ describe('form', function() { }); }); }); + +describe('form animations', function() { + beforeEach(module('ngAnimateMock')); + + function assertValidAnimation(animation, event, className) { + expect(animation.event).toBe(event); + expect(animation.args[1]).toBe(className); + } + + var doc, scope, form; + beforeEach(inject(function($rootScope, $compile, $rootElement, $animate) { + scope = $rootScope.$new(); + doc = jqLite('
'); + $rootElement.append(doc); + $compile(doc)(scope); + $animate.queue = []; + form = scope.myForm; + })); + + afterEach(function() { + dealoc(doc); + }); + + it('should trigger an animation when invalid', inject(function($animate) { + form.$setValidity('required', false); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-valid'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-invalid'); + assertValidAnimation($animate.queue[2], 'removeClass', 'ng-valid-required'); + assertValidAnimation($animate.queue[3], 'addClass', 'ng-invalid-required'); + })); + + it('should trigger an animation when valid', inject(function($animate) { + form.$setValidity('required', false); + + $animate.queue = []; + + form.$setValidity('required', true); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-invalid'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-valid'); + assertValidAnimation($animate.queue[2], 'removeClass', 'ng-invalid-required'); + assertValidAnimation($animate.queue[3], 'addClass', 'ng-valid-required'); + })); + + it('should trigger an animation when dirty', inject(function($animate) { + form.$setDirty(); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-pristine'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-dirty'); + })); + + it('should trigger an animation when pristine', inject(function($animate) { + form.$setDirty(); + + $animate.queue = []; + + form.$setPristine(); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-dirty'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-pristine'); + })); + + it('should trigger custom errors as addClass/removeClass when invalid/valid', inject(function($animate) { + form.$setValidity('custom-error', false); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-valid'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-invalid'); + assertValidAnimation($animate.queue[2], 'removeClass', 'ng-valid-custom-error'); + assertValidAnimation($animate.queue[3], 'addClass', 'ng-invalid-custom-error'); + + $animate.queue = []; + form.$setValidity('custom-error', true); + + assertValidAnimation($animate.queue[0], 'removeClass', 'ng-invalid'); + assertValidAnimation($animate.queue[1], 'addClass', 'ng-valid'); + assertValidAnimation($animate.queue[2], 'removeClass', 'ng-invalid-custom-error'); + assertValidAnimation($animate.queue[3], 'addClass', 'ng-valid-custom-error'); + })); +}); diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index b9f737ac..e3e50e02 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1482,3 +1482,101 @@ describe('input', function() { }); }); }); + +describe('NgModel animations', function() { + beforeEach(module('ngAnimateMock')); + + function findElementAnimations(element, queue) { + var node = element[0]; + var animations = []; + for(var i = 0; i < queue.length; i++) { + var animation = queue[i]; + if(animation.element[0] == node) { + animations.push(animation); + } + } + return animations; + }; + + function assertValidAnimation(animation, event, className) { + expect(animation.event).toBe(event); + expect(animation.args[1]).toBe(className); + } + + var doc, input, scope, model; + beforeEach(inject(function($rootScope, $compile, $rootElement, $animate) { + scope = $rootScope.$new(); + doc = jqLite(''); + $rootElement.append(doc); + $compile(doc)(scope); + $animate.queue = []; + + input = doc.find('input'); + model = scope.myForm.myInput; + })); + + afterEach(function() { + dealoc(input); + }); + + it('should trigger an animation when invalid', inject(function($animate) { + model.$setValidity('required', false); + + var animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-valid'); + assertValidAnimation(animations[1], 'addClass', 'ng-invalid'); + assertValidAnimation(animations[2], 'removeClass', 'ng-valid-required'); + assertValidAnimation(animations[3], 'addClass', 'ng-invalid-required'); + })); + + it('should trigger an animation when valid', inject(function($animate) { + model.$setValidity('required', false); + + $animate.queue = []; + + model.$setValidity('required', true); + + var animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-invalid'); + assertValidAnimation(animations[1], 'addClass', 'ng-valid'); + assertValidAnimation(animations[2], 'removeClass', 'ng-invalid-required'); + assertValidAnimation(animations[3], 'addClass', 'ng-valid-required'); + })); + + it('should trigger an animation when dirty', inject(function($animate) { + model.$setViewValue('some dirty value'); + + var animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-pristine'); + assertValidAnimation(animations[1], 'addClass', 'ng-dirty'); + })); + + it('should trigger an animation when pristine', inject(function($animate) { + model.$setPristine(); + + var animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-dirty'); + assertValidAnimation(animations[1], 'addClass', 'ng-pristine'); + })); + + it('should trigger custom errors as addClass/removeClass when invalid/valid', inject(function($animate) { + model.$setValidity('custom-error', false); + + var animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-valid'); + assertValidAnimation(animations[1], 'addClass', 'ng-invalid'); + assertValidAnimation(animations[2], 'removeClass', 'ng-valid-custom-error'); + assertValidAnimation(animations[3], 'addClass', 'ng-invalid-custom-error'); + + $animate.queue = []; + model.$setValidity('custom-error', true); + + animations = findElementAnimations(input, $animate.queue); + assertValidAnimation(animations[0], 'removeClass', 'ng-invalid'); + assertValidAnimation(animations[1], 'addClass', 'ng-valid'); + assertValidAnimation(animations[2], 'removeClass', 'ng-invalid-custom-error'); + assertValidAnimation(animations[3], 'addClass', 'ng-valid-custom-error'); + })); +}); -- cgit v1.2.3