UNPKG

unassessed

Version:
2,199 lines 79.3 kB
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.unassessed = factory());
}(this, (function () {
  function createCasedFunction(
    expect,
    typesOfValues,
    __assertionString__,
    __camelCasedString__
  ) {
    if (typesOfValues.length === 0) {
      return function (subject) {
        return expect(subject, __assertionString__);
      };
    }

    if (typesOfValues.length === 2) {
      return function (subject, value, value2) {
        if (
          (value && value.__itPlaceholder) ||
          (value2 && value2.__itPlaceholder)
        ) {
          throw new Error(
            ("unassessed: nested assertions are not supported by ." + __camelCasedString__ + "()")
          );
        }

        return expect(subject, __assertionString__, value, value2);
      };
    }

    return function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          ("unassessed: nested assertions are not supported by ." + __camelCasedString__ + "()")
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, __assertionString__ ].concat( args ));
    };
  }

  function createCasedFunctionOpen(expect, __assertionString__) {
    return function (subject, valueOrItPlaceholder) {
      return expect(subject, __assertionString__, valueOrItPlaceholder);
    };
  }

  function createCasedFunctions(expect, casedDefinitions) {
    var casedFunctions = {};

    Object.keys(casedDefinitions).forEach(function (camelCasedString) {
      var ref = casedDefinitions[camelCasedString];
      var assertionString = ref.assertionString;
      var isNestingAllowed = ref.isNestingAllowed;
      var typesOfValues = ref.typesOfValues;

      if (isNestingAllowed) {
        casedFunctions[camelCasedString] = createCasedFunctionOpen(
          expect,
          assertionString
        );
        return;
      }

      casedFunctions[camelCasedString] = createCasedFunction(
        expect,
        typesOfValues,
        assertionString,
        camelCasedString
      );
    });

    return casedFunctions;
  }

  var createCasedFunctions_1 = createCasedFunctions;

  function prepareAssertions(expect) {
    var assertions = {};
    var assertionsWithNestingSuffix = {};

    Object.keys(expect.assertions).forEach(function (key) {
      var value = expect.assertions[key];

      if (key.endsWith(" assertion")) {
        assertionsWithNestingSuffix[key] = value;
      } else {
        assertions[key] = value;
      }
    });

    Object.keys(assertionsWithNestingSuffix).forEach(function (key) {
      var value = assertionsWithNestingSuffix[key];
      var assertionAlternation;
      if (
        value.length > 1 &&
        (assertionAlternation = value.find(function (v) { return v.declaration.endsWith("<assertion>"); }
        ))
      ) {
        var keywithoutSuffix = key.slice(0, -" assertion".length);
        if (assertions[keywithoutSuffix]) {
          assertions[keywithoutSuffix].push(assertionAlternation);
        } else {
          assertions[key] = value;
        }
      }
    });

    return assertions;
  }

  var prepareAssertions_1 = prepareAssertions;

  var ASSERTIONS_TO_EXCLUDE = {
    called: true,
    "when called": true,
    "called with": true,
    "when called with": true,
    "decoded as": true,
    "when decoded as": true,
    "passed as parameter to": true,
    "when passed as parameter to": true,
    "passed as parameters to": true,
    "when passed as parameters to": true,
    "passed as parameter to async": true,
    "when passed as parameter to async": true,
    "passed as parameters to async": true,
    "passed as parameter to constructor": true,
    "when passed as parameter to constructor": true,
    "when passed as parameters to async": true,
    "passed as parameters to constructor": true,
    "when passed as parameters to constructor": true,
    sorted: true,
    "when sorted": true,
    "sorted by": true,
    "when sorted by": true,
    "sorted numerically": true,
    "when sorted numerically": true,
    "when fulfilled": true,
    "when rejected": true,
    // "to only have properties" - only and not are mutually exclusive
    "not to only have own properties": true,
    "not to only have properties": true,
    // "to have key"
    "to have key": true,
    "to only have key": true,
    "to not have key": true,
    "to not only have key": true,
    "not to have key": true,
    // "to have keys"
    "to have keys": true,
    "to only have keys": true,
    "to not have keys": true,
    "to not only have keys": true,
    "not to have keys": true,
    // others
    "to be ok": true,
    "not to be ok": true
  };

  var ASSERTIONS_TO_FORCE_NO_VALUE = {
    "to be falsy": true,
    "to be truthy": true,
    "not to be falsy": true,
    "not to be truthy": true
  };

  function upperCaseFirst(string) {
    return string[0].toUpperCase() + string.slice(1);
  }

  function determineTypesOfValues(expect, assertionString) {
    var originalAssertion = expect.assertions[assertionString];

    var typesOfValues = [];
    originalAssertion.forEach(function (definition) {
      var valueMatches = definition.declaration.match(
        /(?: <([a-zA-z-]+[+?]?(?:[|][a-zA-z-]+)*)>)* <([a-zA-z-]+[+?]?(?:[|][a-zA-z-]+)*)>$/
      );
      if (valueMatches) {
        var validMatches = valueMatches.slice(1).filter(Boolean);
        validMatches.forEach(function (valueMatch, index) {
          if (!valueMatch) { return; }
          var typeOfValue;
          if (typesOfValues.length <= index) {
            typeOfValue = new Set();
            typesOfValues.push(typeOfValue);
          } else {
            typeOfValue = typesOfValues[index];
          }
          var matchedTypes = valueMatch.split("|");
          // handle vararg types by treating them a single arg type
          matchedTypes = matchedTypes.map(function (type) { return type.endsWith("+") ? type.slice(0, -1) : type; }
          );
          matchedTypes.map(function (type) { return typeOfValue.add(type); });
        });
      }
    });
    return typesOfValues;
  }

  function identifyTypesOfValues(typesOfValues) {
    var maybeNested =
      typesOfValues.length > 0 &&
      (typesOfValues[typesOfValues.length - 1].has("assertion?") ||
        typesOfValues[typesOfValues.length - 1].has("assertion"));

    var lastTypesSet = maybeNested && typesOfValues[typesOfValues.length - 1];

    return {
      isMiddleRocket: maybeNested && lastTypesSet.size === 1,
      isNestingAllowed: maybeNested && lastTypesSet.size > 1
    };
  }

  function processUnexpectedInstance(expect, assertions) {
    var casedDefinitions = {};

    Object.keys(assertions).forEach(function (assertionString) {
      var assertionTokens = assertionString.split(" ");
      var assertionOpener = assertionTokens[0];

      if (assertionString in ASSERTIONS_TO_EXCLUDE) {
        return;
      }

      // skip any variants using "non-empty"
      if (assertionTokens.includes("non-empty")) {
        return;
      }

      var camelCasedString =
        assertionOpener +
        assertionTokens
          .slice(1)
          .map(upperCaseFirst)
          .join("");

      var typesOfValues =
        assertionString in ASSERTIONS_TO_FORCE_NO_VALUE
          ? [] // TODO: remove this workaround when "to be ok" string value is removed
          : determineTypesOfValues(expect, assertionString);

      if (
        casedDefinitions[camelCasedString] &&
        casedDefinitions[camelCasedString].isNestingAllowed
      ) {
        // avoid overwriting any assertion where nesting was enabled
        return;
      }

      var ref = identifyTypesOfValues(
        typesOfValues
      );
      var isMiddleRocket = ref.isMiddleRocket;
      var isNestingAllowed = ref.isNestingAllowed;

      // record all information derived for the assertion
      casedDefinitions[camelCasedString] = {
        assertionString: assertionString,
        isMiddleRocket: isMiddleRocket,
        isNestingAllowed: isNestingAllowed,
        typesOfValues: typesOfValues
      };
    });

    return casedDefinitions;
  }

  var processUnexpectedInstance_1 = processUnexpectedInstance;
  var determineTypesOfValues_1 = determineTypesOfValues;
  var identifyTypesOfValues_1 = identifyTypesOfValues;
  processUnexpectedInstance_1.determineTypesOfValues = determineTypesOfValues_1;
  processUnexpectedInstance_1.identifyTypesOfValues = identifyTypesOfValues_1;

  var casedFunctions = function (expect) { return ({
    notToBeTruthy: function (subject) {
      return expect(subject, "not to be truthy");
    },
    toBeTruthy: function (subject) {
      return expect(subject, "to be truthy");
    },
    notToBe: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBe()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be" ].concat( args ));
    },
    toBe: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBe()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be" ].concat( args ));
    },
    notToBeTrue: function (subject) {
      return expect(subject, "not to be true");
    },
    toBeTrue: function (subject) {
      return expect(subject, "to be true");
    },
    notToBeFalse: function (subject) {
      return expect(subject, "not to be false");
    },
    toBeFalse: function (subject) {
      return expect(subject, "to be false");
    },
    notToBeFalsy: function (subject) {
      return expect(subject, "not to be falsy");
    },
    toBeFalsy: function (subject) {
      return expect(subject, "to be falsy");
    },
    notToBeNull: function (subject) {
      return expect(subject, "not to be null");
    },
    toBeNull: function (subject) {
      return expect(subject, "to be null");
    },
    notToBeUndefined: function (subject) {
      return expect(subject, "not to be undefined");
    },
    toBeUndefined: function (subject) {
      return expect(subject, "to be undefined");
    },
    notToBeDefined: function (subject) {
      return expect(subject, "not to be defined");
    },
    toBeDefined: function (subject) {
      return expect(subject, "to be defined");
    },
    notToBeNaN: function (subject) {
      return expect(subject, "not to be NaN");
    },
    toBeNaN: function (subject) {
      return expect(subject, "to be NaN");
    },
    notToBeCloseTo: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeCloseTo()"
        );
      }

      return expect(subject, "not to be close to", value, value2);
    },
    toBeCloseTo: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeCloseTo()"
        );
      }

      return expect(subject, "to be close to", value, value2);
    },
    notToBeA: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeA()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be a" ].concat( args ));
    },
    notToBeAn: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeAn()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be an" ].concat( args ));
    },
    toBeA: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeA()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be a" ].concat( args ));
    },
    toBeAn: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeAn()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be an" ].concat( args ));
    },
    notToBeOneOf: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeOneOf()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be one of" ].concat( args ));
    },
    toBeOneOf: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeOneOf()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be one of" ].concat( args ));
    },
    notToBeAnObject: function (subject) {
      return expect(subject, "not to be an object");
    },
    notToBeAnArray: function (subject) {
      return expect(subject, "not to be an array");
    },
    toBeAnObject: function (subject) {
      return expect(subject, "to be an object");
    },
    toBeAnArray: function (subject) {
      return expect(subject, "to be an array");
    },
    notToBeABoolean: function (subject) {
      return expect(subject, "not to be a boolean");
    },
    notToBeANumber: function (subject) {
      return expect(subject, "not to be a number");
    },
    notToBeAString: function (subject) {
      return expect(subject, "not to be a string");
    },
    notToBeAFunction: function (subject) {
      return expect(subject, "not to be a function");
    },
    notToBeARegexp: function (subject) {
      return expect(subject, "not to be a regexp");
    },
    notToBeARegex: function (subject) {
      return expect(subject, "not to be a regex");
    },
    notToBeARegularExpression: function (subject) {
      return expect(subject, "not to be a regular expression");
    },
    notToBeADate: function (subject) {
      return expect(subject, "not to be a date");
    },
    toBeABoolean: function (subject) {
      return expect(subject, "to be a boolean");
    },
    toBeANumber: function (subject) {
      return expect(subject, "to be a number");
    },
    toBeAString: function (subject) {
      return expect(subject, "to be a string");
    },
    toBeAFunction: function (subject) {
      return expect(subject, "to be a function");
    },
    toBeARegexp: function (subject) {
      return expect(subject, "to be a regexp");
    },
    toBeARegex: function (subject) {
      return expect(subject, "to be a regex");
    },
    toBeARegularExpression: function (subject) {
      return expect(subject, "to be a regular expression");
    },
    toBeADate: function (subject) {
      return expect(subject, "to be a date");
    },
    toBeTheEmptyString: function (subject) {
      return expect(subject, "to be the empty string");
    },
    toBeAnEmptyString: function (subject) {
      return expect(subject, "to be an empty string");
    },
    toBeTheEmptyArray: function (subject) {
      return expect(subject, "to be the empty array");
    },
    toBeAnEmptyArray: function (subject) {
      return expect(subject, "to be an empty array");
    },
    toMatch: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toMatch()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to match" ].concat( args ));
    },
    notToMatch: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToMatch()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to match" ].concat( args ));
    },
    notToHaveOwnProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveOwnProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have own property" ].concat( args ));
    },
    toHaveOwnProperty: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveOwnProperty()"
        );
      }

      return expect(subject, "to have own property", value, value2);
    },
    notToHaveEnumerableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveEnumerableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have enumerable property" ].concat( args ));
    },
    notToHaveConfigurableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveConfigurableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have configurable property" ].concat( args ));
    },
    notToHaveWritableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveWritableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have writable property" ].concat( args ));
    },
    toHaveEnumerableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveEnumerableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have enumerable property" ].concat( args ));
    },
    toHaveConfigurableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveConfigurableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have configurable property" ].concat( args ));
    },
    toHaveWritableProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveWritableProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have writable property" ].concat( args ));
    },
    notToHaveProperty: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveProperty()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have property" ].concat( args ));
    },
    toHaveProperty: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveProperty()"
        );
      }

      return expect(subject, "to have property", value, value2);
    },
    notToHaveOwnProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveOwnProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have own properties" ].concat( args ));
    },
    notToHaveProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have properties" ].concat( args ));
    },
    toOnlyHaveOwnProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toOnlyHaveOwnProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to only have own properties" ].concat( args ));
    },
    toOnlyHaveProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toOnlyHaveProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to only have properties" ].concat( args ));
    },
    toHaveOwnProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveOwnProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have own properties" ].concat( args ));
    },
    toHaveProperties: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveProperties()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have properties" ].concat( args ));
    },
    notToHaveLength: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToHaveLength()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to have length" ].concat( args ));
    },
    toHaveLength: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveLength()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have length" ].concat( args ));
    },
    notToBeEmpty: function (subject) {
      return expect(subject, "not to be empty");
    },
    toBeEmpty: function (subject) {
      return expect(subject, "to be empty");
    },
    notToContain: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToContain()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to contain" ].concat( args ));
    },
    toContain: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toContain()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to contain" ].concat( args ));
    },
    notToBeginWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeginWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to begin with" ].concat( args ));
    },
    toBeginWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeginWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to begin with" ].concat( args ));
    },
    notToStartWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToStartWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to start with" ].concat( args ));
    },
    toStartWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toStartWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to start with" ].concat( args ));
    },
    notToEndWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToEndWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to end with" ].concat( args ));
    },
    toEndWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toEndWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to end with" ].concat( args ));
    },
    notToBeFinite: function (subject) {
      return expect(subject, "not to be finite");
    },
    toBeFinite: function (subject) {
      return expect(subject, "to be finite");
    },
    notToBeInfinite: function (subject) {
      return expect(subject, "not to be infinite");
    },
    toBeInfinite: function (subject) {
      return expect(subject, "to be infinite");
    },
    notToBeWithin: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeWithin()"
        );
      }

      return expect(subject, "not to be within", value, value2);
    },
    toBeWithin: function (subject, value, value2) {
      if (
        (value && value.__itPlaceholder) ||
        (value2 && value2.__itPlaceholder)
      ) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeWithin()"
        );
      }

      return expect(subject, "to be within", value, value2);
    },
    notToBeLessThan: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeLessThan()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be less than" ].concat( args ));
    },
    notToBeBelow: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeBelow()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be below" ].concat( args ));
    },
    toBeLessThan: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeLessThan()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be less than" ].concat( args ));
    },
    toBeBelow: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeBelow()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be below" ].concat( args ));
    },
    notToBeLessThanOrEqualTo: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeLessThanOrEqualTo()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be less than or equal to" ].concat( args ));
    },
    toBeLessThanOrEqualTo: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeLessThanOrEqualTo()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be less than or equal to" ].concat( args ));
    },
    notToBeGreaterThan: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeGreaterThan()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be greater than" ].concat( args ));
    },
    notToBeAbove: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeAbove()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be above" ].concat( args ));
    },
    toBeGreaterThan: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeGreaterThan()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be greater than" ].concat( args ));
    },
    toBeAbove: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeAbove()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be above" ].concat( args ));
    },
    notToBeGreaterThanOrEqualTo: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToBeGreaterThanOrEqualTo()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to be greater than or equal to" ].concat( args ));
    },
    toBeGreaterThanOrEqualTo: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeGreaterThanOrEqualTo()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be greater than or equal to" ].concat( args ));
    },
    notToBePositive: function (subject) {
      return expect(subject, "not to be positive");
    },
    toBePositive: function (subject) {
      return expect(subject, "to be positive");
    },
    notToBeNegative: function (subject) {
      return expect(subject, "not to be negative");
    },
    toBeNegative: function (subject) {
      return expect(subject, "to be negative");
    },
    toEqual: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toEqual()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to equal" ].concat( args ));
    },
    notToEqual: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToEqual()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to equal" ].concat( args ));
    },
    toError: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toError()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to error" ].concat( args ));
    },
    toErrorWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toErrorWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to error with" ].concat( args ));
    },
    notToError: function (subject) {
      return expect(subject, "not to error");
    },
    notToThrow: function (subject) {
      return expect(subject, "not to throw");
    },
    toThrow: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toThrow()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to throw" ].concat( args ));
    },
    toThrowError: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toThrowError()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to throw error" ].concat( args ));
    },
    toThrowException: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toThrowException()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to throw exception" ].concat( args ));
    },
    toSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to satisfy", valueOrItPlaceholder);
    },
    toThrowA: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toThrowA()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to throw a" ].concat( args ));
    },
    toThrowAn: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toThrowAn()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to throw an" ].concat( args ));
    },
    toHaveArity: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveArity()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have arity" ].concat( args ));
    },
    toHaveValuesExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to have values exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveValuesSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to have values satisfying", valueOrItPlaceholder);
    },
    toBeAMapWhoseValuesExhaustivelySatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a map whose values exhaustively satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAMapWhoseValuesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a map whose values satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAHashWhoseValuesExhaustivelySatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a hash whose values exhaustively satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAHashWhoseValuesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a hash whose values satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAnObjectWhoseValuesExhaustivelySatisfy: function (
      subject,
      valueOrItPlaceholder
    ) {
      return expect(
        subject,
        "to be an object whose values exhaustively satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAnObjectWhoseValuesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be an object whose values satisfy",
        valueOrItPlaceholder
      );
    },
    toHaveItemsExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to have items exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveItemsSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to have items satisfying", valueOrItPlaceholder);
    },
    toBeAnArrayWhoseItemsExhaustivelySatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be an array whose items exhaustively satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAnArrayWhoseItemsSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be an array whose items satisfy",
        valueOrItPlaceholder
      );
    },
    toHaveKeysSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to have keys satisfying", valueOrItPlaceholder);
    },
    toBeAMapWhoseKeysSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a map whose keys satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAMapWhosePropertiesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a map whose properties satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAHashWhoseKeysSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a hash whose keys satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAHashWhosePropertiesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be a hash whose properties satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAnObjectWhoseKeysSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be an object whose keys satisfy",
        valueOrItPlaceholder
      );
    },
    toBeAnObjectWhosePropertiesSatisfy: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to be an object whose properties satisfy",
        valueOrItPlaceholder
      );
    },
    notToHaveAValueExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "not to have a value exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    notToHaveAValueSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "not to have a value satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveAValueExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to have a value exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveAValueSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to have a value satisfying", valueOrItPlaceholder);
    },
    notToHaveAnItemExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "not to have an item exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    notToHaveAnItemSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "not to have an item satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveAnItemExhaustivelySatisfying: function (subject, valueOrItPlaceholder) {
      return expect(
        subject,
        "to have an item exhaustively satisfying",
        valueOrItPlaceholder
      );
    },
    toHaveAnItemSatisfying: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to have an item satisfying", valueOrItPlaceholder);
    },
    toBeCanonical: function (subject) {
      return expect(subject, "to be canonical");
    },
    toHaveMessage: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toHaveMessage()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to have message" ].concat( args ));
    },
    toExhaustivelySatisfy: function (subject, valueOrItPlaceholder) {
      return expect(subject, "to exhaustively satisfy", valueOrItPlaceholder);
    },
    notToExhaustivelySatisfy: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToExhaustivelySatisfy()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to exhaustively satisfy" ].concat( args ));
    },
    notToSatisfy: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .notToSatisfy()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "not to satisfy" ].concat( args ));
    },
    toBeRejected: function (subject) {
      return expect(subject, "to be rejected");
    },
    toBeRejectedWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeRejectedWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be rejected with" ].concat( args ));
    },
    toBeRejectedWithErrorExhaustivelySatisfying: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeRejectedWithErrorExhaustivelySatisfying()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(
        void 0, [ subject,
        "to be rejected with error exhaustively satisfying" ].concat( args )
      );
    },
    toBeRejectedWithErrorSatisfying: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeRejectedWithErrorSatisfying()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be rejected with error satisfying" ].concat( args ));
    },
    toBeFulfilled: function (subject) {
      return expect(subject, "to be fulfilled");
    },
    toBeFulfilledWith: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeFulfilledWith()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be fulfilled with" ].concat( args ));
    },
    toBeFulfilledWithValueExhaustivelySatisfying: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeFulfilledWithValueExhaustivelySatisfying()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(
        void 0, [ subject,
        "to be fulfilled with value exhaustively satisfying" ].concat( args )
      );
    },
    toBeFulfilledWithValueSatisfying: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toBeFulfilledWithValueSatisfying()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to be fulfilled with value satisfying" ].concat( args ));
    },
    toCallTheCallback: function (subject) {
      return expect(subject, "to call the callback");
    },
    toCallTheCallbackWithoutError: function (subject) {
      return expect(subject, "to call the callback without error");
    },
    toCallTheCallbackWithError: function (subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      var value = rest.length === 1 ? rest[0] : undefined;
      if (value && value.__itPlaceholder) {
        throw new Error(
          "unassessed: nested assertions are not supported by .toCallTheCallbackWithError()"
        );
      }

      // TODO: type detection may need to be extended to record
      //       an empty argument type so we can restore being able
      //       to enforce the number of arguments where needed
      var args = rest.length === 1 ? [value] : [];

      return expect.apply(void 0, [ subject, "to call the callback with error" ].concat( args ));
    }
  }); };

  /* global weknowhow:false, afterEach: false */
  var unexpected =
    typeof weknowhow !== "undefined" ? weknowhow.expect : require("unexpected");





  function remainingInArray(arr1, arr2) {
    var a = [];
    var finalLength = arr2.length;
    for (var i = arr1.length; i < finalLength; i++) {
      a.push(arr2[i]);
    }
    return a;
  }

  var afterEachAttached = false;
  var onAfterEach = null;

  function ensureAfterEachIsRegistered() {
    if (typeof afterEach === "function" && !afterEachAttached) {
      afterEachAttached = true;
      afterEach(function() {
        var callable = onAfterEach;
        onAfterEach = null;
        if (callable) { callable(); }
      });
    }
  }

  var ItPlaceholder = function ItPlaceholder(name, assertion, args) {
    this.name = name;
    this.assertion = assertion;
    this.args = args;
  };

  ItPlaceholder.prototype.__itPlaceholder = true;

  function attachBoundFunctions(ctx, casedDefinitions, casedFuntions, subject) {
    Object.keys(casedFuntions).forEach(function (fnName) {
      var definition = casedDefinitions[fnName];

      if (definition.isMiddleRocket) {
        return;
      }

      ctx[fnName] = function () {
        var vals = [], len = arguments.length;
        while ( len-- ) vals[ len ] = arguments[ len ];

        return casedFuntions[fnName].apply(casedFuntions, [ subject ].concat( vals ));
      };
    });
  }

  function attachItFunctions(ctx, casedDefinitions, casedFuntions, decrementFn) {
    Object.keys(casedFuntions).forEach(function (fnName) {
      var ref = casedDefinitions[fnName];
      var assertionString = ref.assertionString;
      var isMiddleRocket = ref.isMiddleRocket;
      var isNestingAllowed = ref.isNestingAllowed;

      if (isMiddleRocket) {
        return;
      }

      if (isNestingAllowed) {
        // this assertion has a non-terminating form that takes
        // a value of type <assertion>. Given that .it. functions
        // must terminate an assertion call we will disallow this.
        ctx[fnName] = function () {
          var vals = [], len = arguments.length;
          while ( len-- ) vals[ len ] = arguments[ len ];

          if (vals.length > 0 && vals[0].__itPlaceholder) {
            throw new Error(
              "unassessed: nested assertions are not supported with .it. functions."
            );
          }
          decrementFn();
          return new ItPlaceholder(fnName, assertionString, vals);
        };
        return;
      }

      ctx[fnName] = function () {
        var vals = [], len = arguments.length;
        while ( len-- ) vals[ len ] = arguments[ len ];

        decrementFn();
        return new ItPlaceholder(fnName, assertionString, vals);
      };
    });
  }

  function unwrapItPlaceholder(expect, itPlaceholder) {
    var itAssertion = itPlaceholder.assertion;
    var itArgs = itPlaceholder.args;
    var value; // eslint-disable-next-line prefer-const
    value = expect.it(function (thing) { return expect.apply(void 0, [ thing, itAssertion ].concat( itArgs )); });
    value.__itReference = itPlaceholder;
    return value;
  }

  function _createAssessed(expect, makeCasedFunctions) {
    var executingAssertionCount = 0;

    expect.hook(function (next) {
      return function expectWatcher(context, args) {
        var rest = args.slice(2);
        if (rest.length === 1 && rest[0] instanceof ItPlaceholder) {
          // replace current value argument with the unwapped ItPlaceholder
          args.splice(2, 1, unwrapItPlaceholder(expect, rest[0]));
        }

        executingAssertionCount -= 1;

        var returnValue;
        try {
          returnValue = next(context, args);
        } catch (error) {
          executingAssertionCount = 0;
          throw error;
        }
        if (returnValue.isPending()) {
          returnValue.finally(function () { return (executingAssertionCount = 0); });
        }
        return returnValue;
      };
    });

    expect.addType({
      name: "itFunction",
      base: "expect.it",
      identify: function identify(f) {
        return (
          this.baseType.identify(f) && f.__itReference instanceof ItPlaceholder
        );
      },
      inspect: function inspect(value, _, output, inspect$1) {
        var ref = value.__itReference;
        var assertion = ref.assertion;
        var args = ref.args;

        var argsOutput = output.clone();
        args.forEach(function (arg) {
          argsOutput.sp().append(inspect$1(arg));
        });

        output.error(assertion).append(argsOutput);
      }
    });

    expect.addType({
      name: "ItPlaceholder",
      base: "wrapperObject",
      identify: function identify(v) {
        return v instanceof ItPlaceholder;
      },
      inspect: function inspect(value, depth, output, inspect$1) {
        output.append(this.prefix(output.clone(), value));
        if (value.args.length > 0) {
          value.args.forEach(function (arg, index) {
            if (index > 0) {
              output.text(", ");
            }
            output.appendInspected.apply(output, value.args);
          });
        }
        output.append(this.suffix(output.clone(), value));
        return output;
      },
      unwrap: function unwrap(value) {
        return unwrapItPlaceholder(expect, value);
      },
      prefix: function prefix(output, value) {
        var name = value.name;
        return output.text(("assess.it." + name + "("));
      },
      suffix: function suffix(output) {
        return output.text(")");
      }
    });

    expect.addAssertion(
      "<any> to [exhaustively] satisfy <ItPlaceholder>",
      function (expect, subject, value) {
        var valueType = expect.argTypes[0];

        return expect(
          subject,
          "to [exhaustively] satisfy",
          valueType.unwrap(value)
        );
      }
    );

    makeCasedFunctions = makeCasedFunctions || createCasedFunctions_1;
    var assertions = prepareAssertions_1(expect);
    var casedDefinitions = processUnexpectedInstance_1(expect, assertions);
    var casedFunctions = makeCasedFunctions(expect, casedDefinitions);

    function unassessed(subject) {
      var rest = [], len = arguments.length - 1;
      while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];

      if (rest.length > 0) {
        throw new Error("unassessed: at most one subject argument accepted");
      }

      executingAssertionCount += 1;

      if (!onAfterEach) {
        onAfterEach = function() {
          var currentAssertionCount = executingAssertionCount;
          executingAssertionCount = 0;
          if (currentAssertionCount > 0) {
            throw new Error("unassessed: dangling assertion created");
          }
        };
      }

      var assess = {};

      attachBoundFunctions(assess, casedDefinitions, casedFunctions, subject);

      return assess;
    }

    function assessIt() {
      executingAssertionCount = 0;

      throw new Error(
        "unassessed: asssess.it was called directly. Please use its methods instead."
      );
    }

    attachItFunctions(assessIt, casedDefinitions, casedFunctions, function () {
      executingAssertionCount -= 1;
    });

    unassessed.it = assessIt;

    unassessed.setOutputWidth = function (width) {
      // eslint-disable-next-line no-self-compare
      if (!(typeof width === "number" && width === width && width > 0)) {
        throw new Error("unassessed: invalid output width");
      }

      expect.output.preferredWidth = width;
    };

    unassessed.withPlugins = function () {
      var plugins = [], len = arguments.length;
      while ( len-- ) plugins[ len ] = arguments[ len ];

      var expectWithPlugins = unexpected.clone();
      plugins.forEach(function (plugin) {
        expectWithPlugins.use(plugin);
      });

      // determine if a plugin exposed any properties at the top-level
      var baseExpectKeys = Object.getOwnPropertyNames(unexpected);
      var pluginExpectKeys = Object.getOwnPropertyNames(expectWithPlugins);
      var extraKeys = remainingInArray(baseExpectKeys, pluginExpectKeys);

      var assessWithPlugins = _createAssessed(expectWithPlugins);
      extraKeys.forEach(function (key) { return (assessWithPlugins[key] = expectWithPlugins[key]); });
      return assessWithPlugins;
    };

    unassessed.withUnexpectedPlugins = function () {
      var plugins = [], len = arguments.length;
      while ( len-- ) plugins[ len ] = arguments[ len ];

      return unassessed.withPlugins.apply(unassessed, plugins);
    };

    ensureAfterEachIsRegistered();

    return unassessed;
  }

  function createAssessed(expect) {
    return _createAssessed(expect.clone(), casedFunctions);
  }

  var unassessed = createAssessed(unexpected);

  return unassessed;

})));
//# sourceMappingURL=unassessed.js.map