"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime/helpers/applyDecoratedDescriptor"));

var _immutable = require("immutable");

var _withStateCache = _interopRequireDefault(require("../withStateCache"));

describe('withStateCache', function () {
  var _dec, _dec2, _dec3, _class;

  var stub = sinon.stub();
  var Helper = (_dec = (0, _withStateCache.default)(function (obj) {
    return [['x']];
  }), _dec2 = (0, _withStateCache.default)(function (obj) {
    return [['a', 'b'], ['c']];
  }), _dec3 = (0, _withStateCache.default)(function (obj) {
    return [['x', obj.id]];
  }), (_class =
  /*#__PURE__*/
  function () {
    function Helper(stub) {
      (0, _classCallCheck2.default)(this, Helper);
      this.stub = stub;
      this.internalState = (0, _immutable.fromJS)({
        x: {
          y: null
        }
      });
    }

    (0, _createClass2.default)(Helper, [{
      key: "state",
      value: function state() {
        return this.internalState;
      }
    }, {
      key: "testMethod",
      value: function testMethod() {
        this.stub();
        var x = this.state().get('x');
        return 2 * x.get('y');
      }
    }, {
      key: "testMethod2",
      value: function testMethod2() {
        this.stub();
        var x = this.state().getIn(['a', 'b']).value;
        var y = this.state().getIn(['c']).value;
        return x + y;
      }
    }, {
      key: "testMethod3",
      value: function testMethod3() {
        this.stub();
        var id = this.state().get('id');
        return this.state().getIn(['x', id, 'y']);
      }
    }]);
    return Helper;
  }(), ((0, _applyDecoratedDescriptor2.default)(_class.prototype, "testMethod", [_dec], Object.getOwnPropertyDescriptor(_class.prototype, "testMethod"), _class.prototype), (0, _applyDecoratedDescriptor2.default)(_class.prototype, "testMethod2", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "testMethod2"), _class.prototype), (0, _applyDecoratedDescriptor2.default)(_class.prototype, "testMethod3", [_dec3], Object.getOwnPropertyDescriptor(_class.prototype, "testMethod3"), _class.prototype)), _class));
  var helper;
  beforeEach(function () {
    helper = new Helper(stub);
  });
  afterEach(function () {
    stub.resetHistory();
  });
  context('caching by multiple keys', function () {
    var obj1 = {
      value: 3
    };
    var obj2 = {
      value: 4
    };
    var state = (0, _immutable.fromJS)({
      a: {
        b: null
      },
      c: null
    }).setIn(['a', 'b'], obj1).setIn(['c'], obj2);
    it('calls through to the original method', function () {
      var obj1 = {
        value: 3
      };
      var obj2 = {
        value: 4
      };
      var state = (0, _immutable.fromJS)({
        a: {
          b: null
        },
        c: null
      }).setIn(['a', 'b'], obj1).setIn(['c'], obj2);
      helper.internalState = state;
      expect(helper.testMethod2()).to.eq(7);
      expect(stub.callCount).to.eq(1);
    });
    it('caches when all keys are the same', function () {
      helper.internalState = state;
      expect(helper.testMethod2()).to.eq(7);
      expect(helper.testMethod2()).to.eq(7);
      expect(stub.callCount).to.eq(1);
    });
    it('does not cache when either keys are different', function () {
      helper.internalState = state;
      expect(helper.testMethod2()).to.eq(7);
      var state2 = state.setIn(['a', 'b'], {
        value: 5
      });
      var state3 = state.setIn(['c'], {
        value: 10
      });
      helper.internalState = state2;
      expect(helper.testMethod2()).to.eq(9);
      helper.internalState = state3;
      expect(helper.testMethod2()).to.eq(13);
      expect(stub.callCount).to.eq(3);
    });
  });
  context('caching by one key', function () {
    it('calls the decorated method', function () {
      helper.internalState = (0, _immutable.fromJS)({
        x: {
          y: 5
        }
      });
      expect(helper.testMethod()).to.eq(10);
      expect(stub.callCount).to.eq(1);
    });
    it('caches the decorated method', function () {
      helper.internalState = (0, _immutable.fromJS)({
        x: {
          y: 5
        }
      });
      expect(helper.testMethod()).to.eq(10);
      expect(helper.testMethod()).to.eq(10);
      expect(stub.callCount).to.eq(1);
    });
    it('stops caching on change', function () {
      helper.internalState = (0, _immutable.fromJS)({
        x: {
          y: 5
        }
      });
      expect(helper.testMethod()).to.eq(10);
      helper.internalState = (0, _immutable.fromJS)({
        x: {
          y: 6
        }
      });
      expect(helper.testMethod()).to.eq(12);
      expect(stub.callCount).to.eq(2);
    });
    it('caches by the object calling the method', function () {
      var internalState = (0, _immutable.fromJS)({
        x: {
          y: 5
        }
      });
      helper.internalState = internalState;
      var stub2 = sinon.stub();
      var helper2 = new Helper(stub2);
      helper2.internalState = internalState;
      expect(helper.testMethod()).to.eq(10);
      expect(helper2.testMethod()).to.eq(10);
      expect(stub.callCount).to.eq(1);
      expect(stub2.callCount).to.eq(1);
    });
    context('caching by data that lives on the object', function () {
      it('caches normally', function () {
        var internalState = (0, _immutable.fromJS)({
          id: 'foo',
          x: {
            foo: {
              y: 3
            }
          }
        });
        helper.internalState = internalState;
        expect(helper.testMethod3()).to.eq(3);
        expect(helper.testMethod3()).to.eq(3);
        expect(stub.callCount).to.eq(1);
      });
    });
  });
});