import { createCSSTransitionAnimator } from './CSSTransitionAnimator';
var classNamesRegistry = {
  register: jest.fn(),
  toString: jest.fn()
};

var createMockedElement = function createMockedElement() {
  var element = document.createElement('div');
  var styleChanges = [];
  Object.defineProperty(element, 'style', {
    get: function get() {
      var current = {};
      styleChanges.push(current);
      return current;
    }
  });
  return {
    element: element,
    styleChanges: styleChanges
  };
};

describe('createCSSTransitionAnimator()', function () {
  it('animates based on given PropertyObjects', function () {
    var animator = createCSSTransitionAnimator(classNamesRegistry);

    var _createMockedElement = createMockedElement(),
        element = _createMockedElement.element,
        styleChanges = _createMockedElement.styleChanges;

    animator.animate(element, {
      transform: {
        translateY: 24
      },
      opacity: 0
    }, {
      transform: {
        translateY: 0,
        easing: 'entry',
        duration: 'moderate2'
      },
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    expect(styleChanges).toEqual([{
      willChange: 'transform, opacity'
    }, {
      transform: 'translate3d(0px, 24px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, {
      opacity: '0'
    }, // repaint
    {
      willChange: 'transform, opacity'
    }, {
      transitionProperty: 'transform, opacity'
    }, {
      transitionDuration: '260ms, 120ms'
    }, {
      transitionTimingFunction: 'cubic-bezier(0.1, 0, 0, 1), linear'
    }, {
      transform: 'translate3d(0px, 0px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, {
      opacity: '1'
    }]);
  });
  it('animates progressively without "from" argument', function () {
    var animator = createCSSTransitionAnimator(classNamesRegistry);

    var _createMockedElement2 = createMockedElement(),
        element = _createMockedElement2.element,
        styleChanges = _createMockedElement2.styleChanges;

    animator.animate(element, undefined, {
      transform: {
        translateY: 10,
        duration: 'moderate1'
      }
    });
    animator.animate(element, undefined, {
      transform: {
        translateY: 20,
        duration: 'moderate1'
      }
    });
    expect(styleChanges).toEqual([{
      willChange: 'transform'
    }, {
      transitionProperty: 'transform'
    }, {
      transitionDuration: '180ms'
    }, {
      transitionTimingFunction: 'cubic-bezier(0.35, 0, 0.1, 1)'
    }, {
      transform: 'translate3d(0px, 10px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, // second animate
    {
      willChange: 'transform'
    }, {
      transitionProperty: 'transform'
    }, {
      transitionDuration: '180ms'
    }, {
      transitionTimingFunction: 'cubic-bezier(0.35, 0, 0.1, 1)'
    }, {
      transform: 'translate3d(0px, 20px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }]);
  });
  it('applies "from" progressively without "to" argument', function () {
    var animator = createCSSTransitionAnimator(classNamesRegistry);

    var _createMockedElement3 = createMockedElement(),
        element = _createMockedElement3.element,
        styleChanges = _createMockedElement3.styleChanges;

    animator.animate(element, {
      transform: {
        translateY: 10,
        duration: 'moderate1'
      }
    });
    animator.animate(element, {
      transform: {
        translateY: 20,
        duration: 'moderate1'
      }
    });
    expect(styleChanges).toEqual([{
      willChange: 'transform'
    }, {
      transform: 'translate3d(0px, 10px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, // second animate
    {
      willChange: 'transform'
    }, {
      transform: 'translate3d(0px, 20px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }]);
  });
  it('applies styles after cleanup', function () {
    var animator = createCSSTransitionAnimator(classNamesRegistry);

    var _createMockedElement4 = createMockedElement(),
        element = _createMockedElement4.element,
        styleChanges = _createMockedElement4.styleChanges;

    var props = {
      transform: {
        translateY: 24
      },
      opacity: 0
    };
    animator.animate(element, props);
    animator.cleanup(element);
    animator.animate(element, props);
    expect(styleChanges).toEqual([{
      willChange: 'transform, opacity'
    }, {
      transform: 'translate3d(0px, 24px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, {
      opacity: '0'
    }, // cleanup
    {
      willChange: ''
    }, {
      transitionProperty: ''
    }, {
      transitionDuration: ''
    }, {
      transitionTimingFunction: ''
    }, {
      transform: ''
    }, {
      transformOrigin: ''
    }, {
      width: ''
    }, {
      height: ''
    }, {
      opacity: ''
    }, // second animate
    {
      willChange: 'transform, opacity'
    }, {
      transform: 'translate3d(0px, 24px, 0px) scale3d(1, 1, 1)'
    }, {
      transformOrigin: 'center'
    }, {
      opacity: '0'
    }]);
  });
  it('calls onFinish callback after transition of the last property', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.animate(element, {
      transform: {
        translateY: 24
      },
      opacity: 0
    }, {
      transform: {
        translateY: 0,
        easing: 'entry',
        duration: 'moderate2'
      },
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(1);
  });
  it('calls onFinish callback after transition of a single property', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.animate(element, {
      opacity: 0
    }, {
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(1);
  });
  it('calls onFinish callback after changing the animation', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.animate(element, {
      opacity: 0
    }, {
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    animator.animate(element, {
      transform: {
        translateY: 24
      },
      opacity: 0
    }, {
      transform: {
        translateY: 0,
        easing: 'entry',
        duration: 'moderate2'
      },
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(0);
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(1);
  });
  it('calls onFinish callback only once after each animation', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.animate(element, {
      transform: {
        translateY: 24
      },
      opacity: 0
    }, {
      transform: {
        translateY: 0,
        easing: 'entry',
        duration: 'moderate2'
      },
      opacity: {
        value: 1,
        easing: 'linear',
        duration: 'quick2'
      }
    });
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(1);
  });
  it('calls onFinish callback after instant animation', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.animate(element, {
      transform: {
        translateY: 24
      },
      opacity: 0
    }, {
      transform: {
        translateY: 0
      },
      opacity: {
        value: 1
      },
      duration: 'instant'
    }); // the propertyTransitionEnd callback shouldn't be fired

    expect(callback).toHaveBeenCalledTimes(1);
  });
  it('does not fire onFinish callback after many apply methods', function () {
    var callback = jest.fn();
    var animator = createCSSTransitionAnimator(classNamesRegistry);
    var element = document.createElement('div');
    animator.onFinish(callback);
    animator.apply(element, {
      opacity: 0,
      duration: 'quick2'
    });
    animator.apply(element, {
      opacity: 0.5,
      duration: 'quick2'
    });
    animator.apply(element, {
      opacity: 1,
      duration: 'quick2'
    });
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    animator.propertyTransitionEnd();
    expect(callback).toHaveBeenCalledTimes(0);
  });
});