Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to synchronous test animation in AngularJS 1.3.15?

I guess I have a migration issue with angular-animate.js from version 1.2 to 1.3. Here is my animation

'use strict';
angular.module('cookbook', ['ngAnimate'])
    .animation('.slide-down', function() {
        var NG_HIDE_CLASS = 'ng-hide';

        return {
            beforeAddClass: function(element, className, done) {
                alert('before add');
                if(className === NG_HIDE_CLASS) {
                    element.slideUp(done);
                }
            },
            removeClass: function(element, className, done) {
                if(className === NG_HIDE_CLASS) {
                    element.hide().slideDown(done);
                }
            }
        };
    });

Synchronous test

'use strict';

describe('A Brief Look At Testing Animations(changed) - ', function() {
    var scope;
    var element;
    var $animate;
    var $rootElement;

    beforeEach(module('cookbook', 'ngAnimateMock'));

    describe('Synchronous testing of animations', function() {

        var animatedShow = false;
        var animatedHide = false;

        beforeEach(module(function($animateProvider) {
            $animateProvider.register('.slide-down', function() {
                return {
                    beforeAddClass: function(element, className, done) {
                        debugger;alert(1);
                        animatedHide = true;
                        done();
                    },
                    removeClass: function(element, className, done) {
                        animatedShow = true;
                        done();
                    }
                };
            });
        }));

        beforeEach(inject(function($injector) {
            scope = $injector.get('$rootScope').$new();
            $rootElement = $injector.get('$rootElement');
        }));

        beforeEach(inject(function($compile) {
            element = angular.element('<div class="slide-down" ng-show="hint"></div>');
            $compile(element)(scope);
            scope.$digest();
            $rootElement.append(element);
        }));

        it('should animate to show', function() {
            scope.hint = true;
            scope.$digest();
            expect(animatedShow).toBeTruthy();
        });

        it('should animate to hide', function() {
            scope.hint = true;
            scope.$digest();
            scope.hint = false;
            scope.$digest();
            expect(animatedHide).toBeTruthy();
        });

    });
});

and spec runner

<!DOCTYPE HTML>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Angular Spec Runner</title>

    <link rel="shortcut icon" type="image/png" href="../../lib/jasmine-2.0.0/jasmine_favicon.png">
    <link rel="stylesheet" type="text/css" href="../../lib/jasmine-2.0.0/jasmine.css">

    <script type="text/javascript" src="../../lib/jasmine-2.0.0/jasmine.js"></script>
    <script type="text/javascript" src="../../lib/jasmine-2.0.0/jasmine-html.js"></script>
    <script type="text/javascript" src="../../lib/jasmine-2.0.0/boot.js"></script>

    <script type="text/javascript" src="../../lib/angular-1.2.28_/jquery-1.11.1.min.js"></script>
    <script type="text/javascript" src="../../lib/angular-1.3.15/angular.js"></script>
    <script type="text/javascript" src="../../lib/angular-1.3.15/angular-route.js"></script>
    <script type="text/javascript" src="../../lib/angular-1.3.15/angular-ui-router.js"></script>
    <script type="text/javascript" src="../../lib/angular-1.3.15/angular-mocks.js"></script>
    <script type="text/javascript" src="../../lib/angular-1.2.28_/angular-animate.js"></script>

    <!--DOESN'T WORK WITH 1.3.15-->
    <!--<script type="text/javascript" src="../../lib/angular-1.3.15/angular-animate.js"></script>-->


    <!-- include source files here... -->
    <script type="text/javascript" src="../src/cookbook.js"></script>
    <link rel="stylesheet" href="../src/styles.css">

    <!-- include spec files here... -->
    <script type="text/javascript" src="cookbookSpec.js"></script>

</head>

<body>
</body>

</html>

When I use angular-animate 1.2.28 all tests are passed but after switching to 1.3.15 tests are failed. Now, I am trying to investigate the difference between two versions of angular-animate. Maybe, someone had this trouble. Thank you all for your answers.

like image 799
BILL Avatar asked May 15 '15 14:05

BILL


1 Answers

While trying to put the test to work I realized that I could only:

  • use addClass and removeClass from $animate to add/remove ng-hide class; use "ng-show" directly didn't worked. When using those methods I realized that the method "removeClass" from the object registered as the animation was never called, the ones that were called were: "beforeAddClass" and "beforeRemoveClass", so I changed that. When I google about it I found an issue somewhat related: $animate.removeClass() doesn't work if addClass animation incomplete.
  • use rootScope instead of scope (I could not understand why)

After search a little more I found this comment on an issue; it seems there are some bugs with animations; the comment suggests to use differente versions of angular and angular-animate as there are "a few bugfixes for animate in the pipeline". So I give it a try and use the update versions (v1.4.0-build.4010+sha.213c2a7) and now it seems to work better... Using the ng-show directive now works. (but still only beforeAddClass and beforeRemoveClass are called and could not get scope to works...).

I'm not suggesting you to upgrade (even because v.1.4.0 is not yet released) just pointing that there are issues and bugs around this subject...) Here is the code (with suggested versions v1.4.0-build.4010):

describe('animate', function() {
  var scope, $animate, $rootElement, $compile, $rootscope;

  describe('Synchronous testing of animations', function() {

    var animatedShow = false;
    var animatedHide = false;

    beforeEach(module('cookbook', function( $animateProvider ) {
      animatedShow = false;
      animatedHide = false;

      $animateProvider.register('.slide-down', function() {
        return {
          beforeAddClass: function( element, className, done ) {
            animatedHide = true;
            done();
          },
          beforeRemoveClass: function( element, className, done ) {
            animatedShow = true;
            done();
          }
        };
      });
    }));
    beforeEach(inject(function( _$injector_, _$animate_, _$compile_ ) {
      $compile = _$compile_;
      $animate = _$animate_;
      $rootscope = _$injector_.get('$rootScope');
      scope = _$injector_.get('$rootScope').$new();
      $rootElement = _$injector_.get('$rootElement');
    }));
    it('should animate to hide', function() {
      $rootscope.hint = true;
      var el = $compile('<div class="slide-down" ng-show="hint"></div>')($rootscope);
      $rootElement.append(el);
      angular.element(document.body).append($rootElement);
      $rootscope.$digest();
      $rootscope.hint = false;
      $rootscope.$digest();
      expect(animatedHide).toBeTruthy();
    });
    it('should animate to show', function() {
      $rootscope.hint = false;
      var el = $compile('<div class="slide-down" ng-show="hint"></div>')($rootscope);
      $rootElement.append(el);
      angular.element(document.body).append($rootElement);
      $rootscope.$digest();
      $rootscope.hint = true;
      $rootscope.$digest();
      expect(animatedShow).toBeTruthy();
    });
  });
});

I also agree that this test is not testing the real animation code; maybe an e2e test should be better.

Here is the code using angular and angular-animate v1.3.15 and using addClass and removeClass directly:

    //...the rest of code is identical

    it('should animate to hide', function() {
      var el = $compile('<div class="slide-down"></div>')($rootscope);
      $rootElement.append(el);
      angular.element(document.body).append($rootElement);
      $rootscope.$digest();
      $animate.addClass(el, 'ng-hide');
      $rootscope.$digest();
      expect(animatedHide).toBeTruthy();
    });
    it('should animate to show', function() {
      var el = $compile('<div class="slide-down ng-hide"></div>')($rootscope);
      $rootElement.append(el);
      angular.element(document.body).append($rootElement);
      $rootscope.$digest();
      $animate.removeClass(el, 'ng-hide');
      $rootscope.$digest();
      expect(animatedShow).toBeTruthy();
    });
    //...

I hope this helps... Thanks.

like image 170
jmmtcarvalho Avatar answered Oct 16 '22 01:10

jmmtcarvalho