Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($animateCss): ensure that custom durations do not confuse the gcs cache #11852

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/ngAnimate/animateCss.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {

var timings = computeTimings(node, fullClassName, cacheKey);
var relativeDelay = timings.maxDelay;
maxDelay = Math.max(relativeDelay, 0);
maxDelay = Math.max(relativeDelay, 0) || 0;
maxDuration = timings.maxDuration;

var flags = {};
Expand Down Expand Up @@ -660,7 +660,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
// we need to recalculate the delay value since we used a pre-emptive negative
// delay value and the delay value is required for the final event checking. This
// property will ensure that this will happen after the RAF phase has passed.
if (timings.transitionDuration > 0) {
if (options.duration == null && timings.transitionDuration > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line seems to be sufficient to cause the test to pass. Are the other lines (i.e. maxDelay = Math.max(relativeDelay, 0) || 0;) unnecessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why we have || 0 is because getComputedStyle is mocked out in a lot of parts of the tests and it returns NaN when the computeTimings code is run. Normally (outside of the testing world) getComputedStyle will always return a value of 0s for transition-delay or transition-duration or animation-delay or animation-duration so there is no need to check for null values. This is really just here to make the mocking in tests work.

flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst;
}

Expand Down Expand Up @@ -849,7 +849,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {

timings = computeTimings(node, fullClassName, cacheKey);
relativeDelay = timings.maxDelay;
maxDelay = Math.max(relativeDelay, 0);
maxDelay = Math.max(relativeDelay, 0) || 0;
maxDuration = timings.maxDuration;

if (maxDuration === 0) {
Expand All @@ -866,7 +866,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
? parseFloat(options.delay)
: relativeDelay;

maxDelay = Math.max(relativeDelay, 0);
maxDelay = Math.max(relativeDelay, 0) || 0;

var delayStyle;
if (flags.applyTransitionDelay) {
Expand Down
37 changes: 37 additions & 0 deletions test/ngAnimate/animateCssSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,43 @@ describe("ngAnimate $animateCss", function() {
});
});

it('should avoid applying the same cache to an element a follow-up animation is run on the same element',
inject(function($animateCss, $rootElement, $document) {

function endTransition(element, elapsedTime) {
browserTrigger(element, 'transitionend',
{ timeStamp: Date.now(), elapsedTime: elapsedTime });
}

function startAnimation(element, duration, color) {
$animateCss(element, {
duration: duration,
to: { background: color }
}).start();
triggerAnimationStartFrame();
}

var element = jqLite('<div></div>');
$rootElement.append(element);
jqLite($document[0].body).append($rootElement);

startAnimation(element, 0.5, 'red');
expect(element.attr('style')).toContain('transition');

endTransition(element, 0.5);
expect(element.attr('style')).not.toContain('transition');

startAnimation(element, 0.8, 'blue');
expect(element.attr('style')).toContain('transition');

// Trigger an extra transitionend event that matches the original transition
endTransition(element, 0.5);
expect(element.attr('style')).toContain('transition');

endTransition(element, 0.8);
expect(element.attr('style')).not.toContain('transition');
}));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is hard to follow. How about tidying it up as follows:

    it('should avoid applying the same cache to an element a follow-up animation is run on the same element',
      inject(function($animateCss, $rootElement, $document) {

      function endTransition(element, elapsedTime) {
        browserTrigger(element, 'transitionend',
          { timeStamp: Date.now(), elapsedTime: elapsedTime });
      }

      function startAnimation(element, duration, color) {
        $animateCss(element, {
          duration: duration,
          to: { background: color }
        }).start();
        triggerAnimationStartFrame();
      }

      var element = jqLite('<div class=""></div>');
      $rootElement.append(element);
      jqLite($document[0].body).append($rootElement);

      startAnimation(element, 0.5, 'red');
      expect(element.attr('style')).toContain('transition');

      endTransition(element, 0.5);
      expect(element.attr('style')).not.toContain('transition');

      startAnimation(element, 0.8, 'blue');
      expect(element.attr('style')).toContain('transition');

      // Trigger an extra transitionend event that matches the original transition
      endTransition(element, 0.5);
      expect(element.attr('style')).toContain('transition');

      endTransition(element, 0.8);
      expect(element.attr('style')).not.toContain('transition');
    }));

it('should apply a custom temporary class when a non-structural animation is used',
inject(function($animateCss, $rootElement, $document) {

Expand Down