"use strict";

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

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"));

/**
 * 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
 */
const isIntegrationTest = process.env.TEST_TYPE === 'integration';
exports.isIntegrationTest = isIntegrationTest;

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

_nock.default.back.fixtures = `${__dirname}/../../cassettes`;
/**
 * @private
 */

const 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;

const record = (spec, fn) => new Promise((resolve, reject) => {
  _nock.default.back(`${slugify(spec.getFullName())}.json`, nockDone => {
    const val = fn();

    const isPromise = x => x && x.then;

    const promise = isPromise(val) ? val : Promise.resolve();
    promise.then(res => {
      nockDone();
      resolve(res);
    });
    promise.catch(err => {
      nockDone();
      reject(err);
    });
  });
});
/**
 * @private
 */


exports.record = record;

const getWindow = url => _jsdom.default.JSDOM.fromURL(url, {
  virtualConsole: new _jsdom.default.VirtualConsole()
}).then(dom => 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;

const propTypeErrors = (spec, value) => {
  const getError = key => {
    let error;

    if (typeof spec[key] !== 'function') {
      throw new Error(`Invalid type spec at ${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: ${key} ${error.message}`);
  };

  const keys = Object.keys(spec);

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

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

exports.propTypeErrors = propTypeErrors;