index.js 12 KB

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