"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.propTypeErrors = exports.getWindow = exports.record = exports.slugify = exports.isIntegrationTest = void 0;

var _jsdom = _interopRequireDefault(require("jsdom"));

var _ReactPropTypesSecret = _interopRequireDefault(require("prop-types/lib/ReactPropTypesSecret"));

var _nock = _interopRequireDefault(require("nock"));

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

/**
 * Use this flag to see if the test run is an integration test or not.
 *
 * You might use this in tests to switch between generating randomized vs.
 * stable inputs to functions under test. Typically, if you are doing a
 * playback-record test, you want the inputs to be stable in order to match
 * a recorded API response.
 *
 * @private
 */
var isIntegrationTest = process.env.TEST_TYPE === 'integration';
exports.isIntegrationTest = isIntegrationTest;

_nock["default"].back.setMode(isIntegrationTest ? 'wild' : 'record');

_nock["default"].back.fixtures = "".concat(__dirname, "/../../cassettes");
/**
 * @private
 */

var slugify = function slugify(text) {
  return text.toString().toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
};
/**
 * Conditionally record API responses to a cassette, based on
 * the TEST_TYPE flag. The cassette name is derived from the test.
 *
 * Eg.
 *
 * const spec = test('Test something', () => {
 *   return record(spec, () => {
 *     // ...test here
 *   })
 * })
 *
 * @private
 */


exports.slugify = slugify;

var record = function record(spec, fn) {
  return new Promise(function (resolve, reject) {
    _nock["default"].back("".concat(slugify(spec.getFullName()), ".json"), function (nockDone) {
      var val = fn();

      var isPromise = function isPromise(x) {
        return x && x.then;
      };

      var promise = isPromise(val) ? val : Promise.resolve();
      promise.then(function (res) {
        nockDone();
        resolve(res);
      });
      promise["catch"](function (err) {
        nockDone();
        reject(err);
      });
    });
  });
};
/**
 * @private
 */


exports.record = record;

var getWindow = function getWindow(url) {
  return _jsdom["default"].JSDOM.fromURL(url, {
    virtualConsole: new _jsdom["default"].VirtualConsole()
  }).then(function (dom) {
    return dom.window;
  });
};
/**
 * Perform prop-type validation and return the error strings as an Array
 * or undefined, if there were no errors.
 *
 * @private
 *
 * @param spec {Object} The prop type spec
 * @param value {Object} The value to validate
 * @returns (string[]|undefined)
 */


exports.getWindow = getWindow;

var propTypeErrors = function propTypeErrors(spec, value) {
  var getError = function getError(key) {
    var error;

    if (typeof spec[key] !== 'function') {
      throw new Error("Invalid type spec at ".concat(key, " - expected a function"));
    }

    try {
      error = spec[key](value, key, 'assertion', '', '', _ReactPropTypesSecret["default"]);
    } catch (ex) {
      error = ex;
    }

    return error && (!(error instanceof Error) ? 'Invalid type spec - function must return `null` or an `Error`' : "Failed prop type: ".concat(key, " ").concat(error.message));
  };

  var keys = Object.keys(spec);

  if (keys.length === 0) {
    return [new Error('Invalid type spec - expected at least one key')];
  }

  var errors = keys.map(getError).filter(function (x) {
    return Boolean(x);
  });
  return errors.length > 0 ? errors : undefined;
};

exports.propTypeErrors = propTypeErrors;