index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. 'use strict';
  2. var matcherUtils = _interopRequireWildcard(require('jest-matcher-utils'));
  3. var _utils = require('./utils');
  4. var _matchers = _interopRequireDefault(require('./matchers'));
  5. var _spyMatchers = _interopRequireDefault(require('./spyMatchers'));
  6. var _toThrowMatchers = _interopRequireWildcard(require('./toThrowMatchers'));
  7. var _jasmineUtils = require('./jasmineUtils');
  8. var _asymmetricMatchers = require('./asymmetricMatchers');
  9. var _jestMatchersObject = require('./jestMatchersObject');
  10. var _extractExpectedAssertionsErrors = _interopRequireDefault(
  11. require('./extractExpectedAssertionsErrors')
  12. );
  13. function _interopRequireDefault(obj) {
  14. return obj && obj.__esModule ? obj : {default: obj};
  15. }
  16. function _interopRequireWildcard(obj) {
  17. if (obj && obj.__esModule) {
  18. return obj;
  19. } else {
  20. var newObj = {};
  21. if (obj != null) {
  22. for (var key in obj) {
  23. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  24. var desc =
  25. Object.defineProperty && Object.getOwnPropertyDescriptor
  26. ? Object.getOwnPropertyDescriptor(obj, key)
  27. : {};
  28. if (desc.get || desc.set) {
  29. Object.defineProperty(newObj, key, desc);
  30. } else {
  31. newObj[key] = obj[key];
  32. }
  33. }
  34. }
  35. }
  36. newObj.default = obj;
  37. return newObj;
  38. }
  39. }
  40. var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
  41. function _objectSpread(target) {
  42. for (var i = 1; i < arguments.length; i++) {
  43. var source = arguments[i] != null ? arguments[i] : {};
  44. var ownKeys = Object.keys(source);
  45. if (typeof Object.getOwnPropertySymbols === 'function') {
  46. ownKeys = ownKeys.concat(
  47. Object.getOwnPropertySymbols(source).filter(function(sym) {
  48. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  49. })
  50. );
  51. }
  52. ownKeys.forEach(function(key) {
  53. _defineProperty(target, key, source[key]);
  54. });
  55. }
  56. return target;
  57. }
  58. var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
  59. var Promise = global[Symbol.for('jest-native-promise')] || global.Promise;
  60. function _defineProperty(obj, key, value) {
  61. if (key in obj) {
  62. Object.defineProperty(obj, key, {
  63. value: value,
  64. enumerable: true,
  65. configurable: true,
  66. writable: true
  67. });
  68. } else {
  69. obj[key] = value;
  70. }
  71. return obj;
  72. }
  73. class JestAssertionError extends Error {
  74. constructor(...args) {
  75. super(...args);
  76. _defineProperty(this, 'matcherResult', void 0);
  77. }
  78. }
  79. const isPromise = obj =>
  80. !!obj &&
  81. (typeof obj === 'object' || typeof obj === 'function') &&
  82. typeof obj.then === 'function';
  83. const createToThrowErrorMatchingSnapshotMatcher = function createToThrowErrorMatchingSnapshotMatcher(
  84. matcher
  85. ) {
  86. return function(received, testNameOrInlineSnapshot) {
  87. return matcher.apply(this, [received, testNameOrInlineSnapshot, true]);
  88. };
  89. };
  90. const getPromiseMatcher = (name, matcher) => {
  91. if (name === 'toThrow' || name === 'toThrowError') {
  92. return (0, _toThrowMatchers.createMatcher)(name, true);
  93. } else if (
  94. name === 'toThrowErrorMatchingSnapshot' ||
  95. name === 'toThrowErrorMatchingInlineSnapshot'
  96. ) {
  97. return createToThrowErrorMatchingSnapshotMatcher(matcher);
  98. }
  99. return null;
  100. };
  101. const expect = (actual, ...rest) => {
  102. if (rest.length !== 0) {
  103. throw new Error('Expect takes at most one argument.');
  104. }
  105. const allMatchers = (0, _jestMatchersObject.getMatchers)();
  106. const expectation = {
  107. not: {},
  108. rejects: {
  109. not: {}
  110. },
  111. resolves: {
  112. not: {}
  113. }
  114. };
  115. const err = new JestAssertionError();
  116. Object.keys(allMatchers).forEach(name => {
  117. const matcher = allMatchers[name];
  118. const promiseMatcher = getPromiseMatcher(name, matcher) || matcher;
  119. expectation[name] = makeThrowingMatcher(matcher, false, '', actual);
  120. expectation.not[name] = makeThrowingMatcher(matcher, true, '', actual);
  121. expectation.resolves[name] = makeResolveMatcher(
  122. name,
  123. promiseMatcher,
  124. false,
  125. actual,
  126. err
  127. );
  128. expectation.resolves.not[name] = makeResolveMatcher(
  129. name,
  130. promiseMatcher,
  131. true,
  132. actual,
  133. err
  134. );
  135. expectation.rejects[name] = makeRejectMatcher(
  136. name,
  137. promiseMatcher,
  138. false,
  139. actual,
  140. err
  141. );
  142. expectation.rejects.not[name] = makeRejectMatcher(
  143. name,
  144. promiseMatcher,
  145. true,
  146. actual,
  147. err
  148. );
  149. });
  150. return expectation;
  151. };
  152. const getMessage = message =>
  153. (message && message()) ||
  154. matcherUtils.RECEIVED_COLOR('No message was specified for this matcher.');
  155. const makeResolveMatcher = (matcherName, matcher, isNot, actual, outerErr) => (
  156. ...args
  157. ) => {
  158. const options = {
  159. isNot,
  160. promise: 'resolves'
  161. };
  162. if (!isPromise(actual)) {
  163. throw new JestAssertionError(
  164. matcherUtils.matcherErrorMessage(
  165. matcherUtils.matcherHint(matcherName, undefined, '', options),
  166. `${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,
  167. matcherUtils.printWithType(
  168. 'Received',
  169. actual,
  170. matcherUtils.printReceived
  171. )
  172. )
  173. );
  174. }
  175. const innerErr = new JestAssertionError();
  176. return actual.then(
  177. result =>
  178. makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply(
  179. null,
  180. args
  181. ),
  182. reason => {
  183. outerErr.message =
  184. matcherUtils.matcherHint(matcherName, undefined, '', options) +
  185. '\n\n' +
  186. `Received promise rejected instead of resolved\n` +
  187. `Rejected to value: ${matcherUtils.printReceived(reason)}`;
  188. return Promise.reject(outerErr);
  189. }
  190. );
  191. };
  192. const makeRejectMatcher = (matcherName, matcher, isNot, actual, outerErr) => (
  193. ...args
  194. ) => {
  195. const options = {
  196. isNot,
  197. promise: 'rejects'
  198. };
  199. if (!isPromise(actual)) {
  200. throw new JestAssertionError(
  201. matcherUtils.matcherErrorMessage(
  202. matcherUtils.matcherHint(matcherName, undefined, '', options),
  203. `${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,
  204. matcherUtils.printWithType(
  205. 'Received',
  206. actual,
  207. matcherUtils.printReceived
  208. )
  209. )
  210. );
  211. }
  212. const innerErr = new JestAssertionError();
  213. return actual.then(
  214. result => {
  215. outerErr.message =
  216. matcherUtils.matcherHint(matcherName, undefined, '', options) +
  217. '\n\n' +
  218. `Received promise resolved instead of rejected\n` +
  219. `Resolved to value: ${matcherUtils.printReceived(result)}`;
  220. return Promise.reject(outerErr);
  221. },
  222. reason =>
  223. makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(
  224. null,
  225. args
  226. )
  227. );
  228. };
  229. const makeThrowingMatcher = (matcher, isNot, promise, actual, err) =>
  230. function throwingMatcher(...args) {
  231. let throws = true;
  232. const utils = _objectSpread({}, matcherUtils, {
  233. iterableEquality: _utils.iterableEquality,
  234. subsetEquality: _utils.subsetEquality
  235. });
  236. const matcherContext = _objectSpread(
  237. {
  238. // When throws is disabled, the matcher will not throw errors during test
  239. // execution but instead add them to the global matcher state. If a
  240. // matcher throws, test execution is normally stopped immediately. The
  241. // snapshot matcher uses it because we want to log all snapshot
  242. // failures in a test.
  243. dontThrow: () => (throws = false)
  244. },
  245. (0, _jestMatchersObject.getState)(),
  246. {
  247. equals: _jasmineUtils.equals,
  248. error: err,
  249. isNot,
  250. promise,
  251. utils
  252. }
  253. );
  254. const processResult = (result, asyncError) => {
  255. _validateResult(result);
  256. (0, _jestMatchersObject.getState)().assertionCalls++;
  257. if ((result.pass && isNot) || (!result.pass && !isNot)) {
  258. // XOR
  259. const message = getMessage(result.message);
  260. let error;
  261. if (err) {
  262. error = err;
  263. error.message = message;
  264. } else if (asyncError) {
  265. error = asyncError;
  266. error.message = message;
  267. } else {
  268. error = new JestAssertionError(message); // Try to remove this function from the stack trace frame.
  269. // Guard for some environments (browsers) that do not support this feature.
  270. if (Error.captureStackTrace) {
  271. Error.captureStackTrace(error, throwingMatcher);
  272. }
  273. } // Passing the result of the matcher with the error so that a custom
  274. // reporter could access the actual and expected objects of the result
  275. // for example in order to display a custom visual diff
  276. error.matcherResult = result;
  277. if (throws) {
  278. throw error;
  279. } else {
  280. (0, _jestMatchersObject.getState)().suppressedErrors.push(error);
  281. }
  282. }
  283. };
  284. const handlError = error => {
  285. if (
  286. matcher[_jestMatchersObject.INTERNAL_MATCHER_FLAG] === true &&
  287. !(error instanceof JestAssertionError) &&
  288. error.name !== 'PrettyFormatPluginError' && // Guard for some environments (browsers) that do not support this feature.
  289. Error.captureStackTrace
  290. ) {
  291. // Try to remove this and deeper functions from the stack trace frame.
  292. Error.captureStackTrace(error, throwingMatcher);
  293. }
  294. throw error;
  295. };
  296. let potentialResult;
  297. try {
  298. potentialResult = matcher.call(matcherContext, actual, ...args);
  299. if (isPromise(potentialResult)) {
  300. const asyncResult = potentialResult;
  301. const asyncError = new JestAssertionError();
  302. if (Error.captureStackTrace) {
  303. Error.captureStackTrace(asyncError, throwingMatcher);
  304. }
  305. return asyncResult
  306. .then(aResult => processResult(aResult, asyncError))
  307. .catch(error => handlError(error));
  308. } else {
  309. const syncResult = potentialResult;
  310. return processResult(syncResult);
  311. }
  312. } catch (error) {
  313. return handlError(error);
  314. }
  315. };
  316. expect.extend = matchers =>
  317. (0, _jestMatchersObject.setMatchers)(matchers, false, expect);
  318. expect.anything = _asymmetricMatchers.anything;
  319. expect.any = _asymmetricMatchers.any;
  320. expect.not = {
  321. arrayContaining: _asymmetricMatchers.arrayNotContaining,
  322. objectContaining: _asymmetricMatchers.objectNotContaining,
  323. stringContaining: _asymmetricMatchers.stringNotContaining,
  324. stringMatching: _asymmetricMatchers.stringNotMatching
  325. };
  326. expect.objectContaining = _asymmetricMatchers.objectContaining;
  327. expect.arrayContaining = _asymmetricMatchers.arrayContaining;
  328. expect.stringContaining = _asymmetricMatchers.stringContaining;
  329. expect.stringMatching = _asymmetricMatchers.stringMatching;
  330. const _validateResult = result => {
  331. if (
  332. typeof result !== 'object' ||
  333. typeof result.pass !== 'boolean' ||
  334. (result.message &&
  335. typeof result.message !== 'string' &&
  336. typeof result.message !== 'function')
  337. ) {
  338. throw new Error(
  339. 'Unexpected return from a matcher function.\n' +
  340. 'Matcher functions should ' +
  341. 'return an object in the following format:\n' +
  342. ' {message?: string | function, pass: boolean}\n' +
  343. `'${matcherUtils.stringify(result)}' was returned`
  344. );
  345. }
  346. };
  347. function assertions(expected) {
  348. const error = new Error();
  349. if (Error.captureStackTrace) {
  350. Error.captureStackTrace(error, assertions);
  351. }
  352. (0, _jestMatchersObject.getState)().expectedAssertionsNumber = expected;
  353. (0, _jestMatchersObject.getState)().expectedAssertionsNumberError = error;
  354. }
  355. function hasAssertions(...args) {
  356. const error = new Error();
  357. if (Error.captureStackTrace) {
  358. Error.captureStackTrace(error, hasAssertions);
  359. }
  360. matcherUtils.ensureNoExpected(args[0], '.hasAssertions');
  361. (0, _jestMatchersObject.getState)().isExpectingAssertions = true;
  362. (0, _jestMatchersObject.getState)().isExpectingAssertionsError = error;
  363. } // add default jest matchers
  364. (0, _jestMatchersObject.setMatchers)(_matchers.default, true, expect);
  365. (0, _jestMatchersObject.setMatchers)(_spyMatchers.default, true, expect);
  366. (0, _jestMatchersObject.setMatchers)(_toThrowMatchers.default, true, expect);
  367. expect.addSnapshotSerializer = () => void 0;
  368. expect.assertions = assertions;
  369. expect.hasAssertions = hasAssertions;
  370. expect.getState = _jestMatchersObject.getState;
  371. expect.setState = _jestMatchersObject.setState;
  372. expect.extractExpectedAssertionsErrors =
  373. _extractExpectedAssertionsErrors.default;
  374. const expectExport = expect; // eslint-disable-next-line no-redeclare
  375. module.exports = expectExport;