"use strict";

require("core-js/modules/es.symbol");

require("core-js/modules/es.array.concat");

require("core-js/modules/es.array.filter");

require("core-js/modules/es.array.for-each");

require("core-js/modules/es.object.define-properties");

require("core-js/modules/es.object.define-property");

require("core-js/modules/es.object.get-own-property-descriptor");

require("core-js/modules/es.object.get-own-property-descriptors");

require("core-js/modules/es.object.keys");

require("core-js/modules/web.dom-collections.for-each");

var _react = _interopRequireDefault(require("react"));

var _enzyme = require("enzyme");

var _ = _interopRequireDefault(require("."));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var values = {
  a: true,
  b: null,
  c: ['1', '2'],
  d: {
    d1: 'nested'
  }
};

var noop = function noop() {};

var context = {
  ffOnChange: noop,
  ffGetValue: function ffGetValue() {
    return values;
  },
  ffFullName: function ffFullName() {
    return [];
  },
  formSubscription: {
    subscribe: noop,
    unsubscribe: noop
  }
};
describe('components/ValueSubscriber', function () {
  test('provides access to the form values without a name', function () {
    var wrapper = (0, _enzyme.shallow)(_react["default"].createElement(_["default"], null), {
      context: context
    });
    var component = wrapper.instance();
    expect(component.getChildContext().ffGetValue()).toBe(values);
  });
  test('uses the name for nesting values and onChange events', function () {
    var testChange = function testChange(name, value, onChangeArg, event) {
      var ffOnChange = jest.fn();
      var wrapper = (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
        name: name
      }), {
        context: _objectSpread({}, context, {
          ffOnChange: ffOnChange
        })
      });
      var component = wrapper.instance();
      var childContext = component.getChildContext();
      expect(childContext.ffGetValue()).toBe(value);
      component.onChange(onChangeArg);
      expect(ffOnChange).toHaveBeenCalledTimes(1);
      expect(ffOnChange.mock.calls[0][0].target).toEqual(event);
    };

    testChange('a', values.a, {
      target: {
        name: '',
        value: false
      }
    }, {
      name: ['a'],
      value: false
    });
    testChange('a', values.a, false, {
      name: ['a'],
      value: false
    });
    testChange('b', values.b, {
      test: true
    }, {
      name: ['b'],
      value: {
        test: true
      }
    });
    testChange('c', values.c, ['3', '4'], {
      name: ['c'],
      value: ['3', '4']
    });
    testChange('c', values.c, {
      target: {
        name: '0',
        value: '5'
      }
    }, {
      name: ['c', '0'],
      value: '5'
    });
    testChange('d', values.d, {
      d1: 'replaced'
    }, {
      name: ['d'],
      value: {
        d1: 'replaced'
      }
    });
    testChange('d', values.d, {
      target: {
        name: 'd1',
        value: 'replaced'
      }
    }, {
      name: ['d', 'd1'],
      value: 'replaced'
    });
  });
  test('handles numbers for accessing array values', function () {
    var ffOnChange = jest.fn();
    var wrapper = (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
      name: "0"
    }), {
      context: _objectSpread({}, context, {
        ffOnChange: ffOnChange,
        ffGetValue: function ffGetValue() {
          return values.c;
        }
      })
    });
    var component = wrapper.instance();
    expect(component.getValue()).toBe(values.c[0]);
    component.onChange('replaced');
    expect(ffOnChange).toHaveBeenCalledTimes(1);
    expect(ffOnChange.mock.calls[0][0].target).toEqual({
      name: ['0'],
      value: 'replaced'
    });
  });
  test('only rerenders when the value changes, or props/state change', function () {
    var testValue = values;
    var wrapper = (0, _enzyme.mount)(_react["default"].createElement(_["default"], null), {
      context: _objectSpread({}, context, {
        ffGetValue: function ffGetValue() {
          return testValue;
        }
      })
    });
    var shouldUpdateSpy = jest.spyOn(wrapper.instance(), 'shouldComponentUpdate');
    expect(shouldUpdateSpy).not.toHaveBeenCalled();
    wrapper.setProps({});
    expect(shouldUpdateSpy).toHaveLastReturnedWith(false);
    wrapper.setState({});
    expect(shouldUpdateSpy).toHaveLastReturnedWith(false);
    wrapper.setProps({
      'data-test': true
    });
    expect(shouldUpdateSpy).toHaveLastReturnedWith(true);
    wrapper.setState({
      test: true
    });
    expect(shouldUpdateSpy).toHaveLastReturnedWith(true);
    testValue = _objectSpread({}, testValue, {
      a: false
    });
    wrapper.setState({});
    expect(shouldUpdateSpy).toHaveLastReturnedWith(true);
  });
  test('should throw an invariant when fetching a missing value', function () {
    expect(function () {
      return (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
        name: "thisKeyIsMissing"
      }), {
        context: context
      });
    }).toThrowError('"thisKeyIsMissing" must have a value. Please check the handler\'s getDefaults() method.');
  });
  test('nests context.ffFullName()', function () {
    var getFullName = function getFullName(name, childName) {
      var val = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : values;
      return (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
        name: childName
      }), {
        context: _objectSpread({}, context, {
          ffFullName: function ffFullName() {
            return [].concat(name);
          },
          ffGetValue: function ffGetValue() {
            return val;
          }
        })
      }).instance().getChildContext().ffFullName();
    };

    expect(getFullName('d')).toEqual(['d']);
    expect(getFullName('d', 'd1', {
      d1: true
    })).toEqual(['d', 'd1']);
    expect(getFullName('c', '0', [false, true])).toEqual(['c', '0']);
  });
  test('enforces onChange not altering value types', function () {
    var changeType = function changeType(oldVal, newVal, name) {
      return (0, _enzyme.shallow)(_react["default"].createElement(_["default"], null), {
        context: _objectSpread({}, context, {
          ffGetValue: function ffGetValue() {
            return oldVal;
          }
        })
      }).instance().onChange({
        target: {
          name: name,
          value: newVal
        }
      });
    }; // Same type


    expect(function () {
      return changeType(true, false);
    }).not.toThrowError();
    expect(function () {
      return changeType(0, 1);
    }).not.toThrowError();
    expect(function () {
      return changeType('a', 'b');
    }).not.toThrowError();
    expect(function () {
      return changeType([], []);
    }).not.toThrowError();
    expect(function () {
      return changeType({}, {});
    }).not.toThrowError(); // Same type with new type inside

    expect(function () {
      return changeType([], ['test']);
    }).not.toThrowError();
    expect(function () {
      return changeType({}, {
        test: 'test'
      });
    }).not.toThrowError(); // Same type with no type inside

    expect(function () {
      return changeType(['test'], []);
    }).not.toThrowError();
    expect(function () {
      return changeType({
        test: 'test'
      }, {});
    }).not.toThrowError();
    expect(function () {
      return changeType(true, 'string');
    }).toThrowError();
    expect(function () {
      return changeType('0', 0);
    }).toThrowError();
    expect(function () {
      return changeType([], {});
    }).toThrowError();
    expect(function () {
      return changeType([], true);
    }).toThrowError();
    expect(function () {
      return changeType({}, []);
    }).toThrowError();
    expect(function () {
      return changeType({}, true);
    }).toThrowError(); // Same type with different type inside

    expect(function () {
      return changeType(['a'], [true]);
    }).toThrowError();
    expect(function () {
      return changeType({
        test: 'a'
      }, {
        test: true
      });
    }).toThrowError(); // Allow replacing values with null

    expect(function () {
      return changeType([], null);
    }).not.toThrowError();
    expect(function () {
      return changeType(['test'], [null]);
    }).not.toThrowError();
    expect(function () {
      return changeType({}, null);
    }).not.toThrowError();
    expect(function () {
      return changeType({
        test: 'test'
      }, {
        test: null
      });
    }).not.toThrowError(); // Test name paths

    expect(function () {
      return changeType({
        test: []
      }, 'replace array', 'test');
    }).toThrowError();
    expect(function () {
      return changeType({
        test: []
      }, 'replace array', ['test']);
    }).toThrowError();
    expect(function () {
      return changeType({
        test: [{}]
      }, 'replace array', ['test', 0]);
    }).toThrowError(); // Allow strings to change to numbers, if the original was a number

    expect(function () {
      return changeType(5, '4');
    }).not.toThrowError();
    expect(function () {
      return changeType(5, 'a');
    }).toThrowError();
  });
  test('allow values to be undefined with ignoreUndefined=true', function () {
    expect(function () {
      return (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
        name: "e"
      }), {
        context: context
      });
    }).toThrow();
    expect(function () {
      return (0, _enzyme.shallow)(_react["default"].createElement(_["default"], {
        name: "e",
        ignoreUndefined: true
      }), {
        context: context
      });
    }).not.toThrow();
  });
});