spyMatchers.js 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _jestGetType = _interopRequireWildcard(require('jest-get-type'));
  7. var _jestMatcherUtils = require('jest-matcher-utils');
  8. var _jasmineUtils = require('./jasmineUtils');
  9. var _utils = require('./utils');
  10. function _interopRequireWildcard(obj) {
  11. if (obj && obj.__esModule) {
  12. return obj;
  13. } else {
  14. var newObj = {};
  15. if (obj != null) {
  16. for (var key in obj) {
  17. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  18. var desc =
  19. Object.defineProperty && Object.getOwnPropertyDescriptor
  20. ? Object.getOwnPropertyDescriptor(obj, key)
  21. : {};
  22. if (desc.get || desc.set) {
  23. Object.defineProperty(newObj, key, desc);
  24. } else {
  25. newObj[key] = obj[key];
  26. }
  27. }
  28. }
  29. }
  30. newObj.default = obj;
  31. return newObj;
  32. }
  33. }
  34. /**
  35. * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  36. *
  37. * This source code is licensed under the MIT license found in the
  38. * LICENSE file in the root directory of this source tree.
  39. */
  40. // The optional property of matcher context is true if undefined.
  41. const isExpand = expand => expand !== false;
  42. const PRINT_LIMIT = 3;
  43. const NO_ARGUMENTS = 'called with 0 arguments';
  44. const printExpectedArgs = expected =>
  45. expected.length === 0
  46. ? NO_ARGUMENTS
  47. : expected.map(arg => (0, _jestMatcherUtils.printExpected)(arg)).join(', ');
  48. const printReceivedArgs = (received, expected) =>
  49. received.length === 0
  50. ? NO_ARGUMENTS
  51. : received
  52. .map((arg, i) =>
  53. Array.isArray(expected) &&
  54. i < expected.length &&
  55. isEqualValue(expected[i], arg)
  56. ? printCommon(arg)
  57. : (0, _jestMatcherUtils.printReceived)(arg)
  58. )
  59. .join(', ');
  60. const printCommon = val =>
  61. (0, _jestMatcherUtils.DIM_COLOR)((0, _jestMatcherUtils.stringify)(val));
  62. const isEqualValue = (expected, received) =>
  63. (0, _jasmineUtils.equals)(expected, received, [_utils.iterableEquality]);
  64. const isEqualCall = (expected, received) => isEqualValue(expected, received);
  65. const isEqualReturn = (expected, result) =>
  66. result.type === 'return' && isEqualValue(expected, result.value);
  67. const countReturns = results =>
  68. results.reduce((n, result) => (result.type === 'return' ? n + 1 : n), 0);
  69. const printNumberOfReturns = (countReturns, countCalls) =>
  70. `\nNumber of returns: ${(0, _jestMatcherUtils.printReceived)(countReturns)}` +
  71. (countCalls !== countReturns
  72. ? `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(countCalls)}`
  73. : '');
  74. // Given a label, return a function which given a string,
  75. // right-aligns it preceding the colon in the label.
  76. const getRightAlignedPrinter = label => {
  77. // Assume that the label contains a colon.
  78. const index = label.indexOf(':');
  79. const suffix = label.slice(index);
  80. return (string, isExpectedCall) =>
  81. (isExpectedCall
  82. ? '->' + ' '.repeat(Math.max(0, index - 2 - string.length))
  83. : ' '.repeat(Math.max(index - string.length))) +
  84. string +
  85. suffix;
  86. };
  87. const printReceivedCallsNegative = (
  88. expected,
  89. indexedCalls,
  90. isOnlyCall,
  91. iExpectedCall
  92. ) => {
  93. if (indexedCalls.length === 0) {
  94. return '';
  95. }
  96. const label = 'Received: ';
  97. if (isOnlyCall) {
  98. return label + printReceivedArgs(indexedCalls[0], expected) + '\n';
  99. }
  100. const printAligned = getRightAlignedPrinter(label);
  101. return (
  102. 'Received\n' +
  103. indexedCalls.reduce(
  104. (printed, [i, args]) =>
  105. printed +
  106. printAligned(String(i + 1), i === iExpectedCall) +
  107. printReceivedArgs(args, expected) +
  108. '\n',
  109. ''
  110. )
  111. );
  112. };
  113. const printExpectedReceivedCallsPositive = (
  114. expected,
  115. indexedCalls,
  116. expand,
  117. isOnlyCall,
  118. iExpectedCall
  119. ) => {
  120. const expectedLine = `Expected: ${printExpectedArgs(expected)}\n`;
  121. if (indexedCalls.length === 0) {
  122. return expectedLine;
  123. }
  124. const label = 'Received: ';
  125. if (isOnlyCall && (iExpectedCall === 0 || iExpectedCall === undefined)) {
  126. const received = indexedCalls[0][1];
  127. if (isLineDiffableCall(expected, received)) {
  128. // Display diff without indentation.
  129. const lines = [
  130. (0, _jestMatcherUtils.EXPECTED_COLOR)('- Expected'),
  131. (0, _jestMatcherUtils.RECEIVED_COLOR)('+ Received'),
  132. ''
  133. ];
  134. const length = Math.max(expected.length, received.length);
  135. for (let i = 0; i < length; i += 1) {
  136. if (i < expected.length && i < received.length) {
  137. if (isEqualValue(expected[i], received[i])) {
  138. lines.push(` ${printCommon(received[i])},`);
  139. continue;
  140. }
  141. if (isLineDiffableArg(expected[i], received[i])) {
  142. const difference = (0, _jestMatcherUtils.diff)(
  143. expected[i],
  144. received[i],
  145. {
  146. expand
  147. }
  148. );
  149. if (
  150. typeof difference === 'string' &&
  151. difference.includes('- Expected') &&
  152. difference.includes('+ Received')
  153. ) {
  154. // Omit annotation in case multiple args have diff.
  155. lines.push(
  156. difference
  157. .split('\n')
  158. .slice(3)
  159. .join('\n') + ','
  160. );
  161. continue;
  162. }
  163. }
  164. }
  165. if (i < expected.length) {
  166. lines.push(
  167. (0, _jestMatcherUtils.EXPECTED_COLOR)(
  168. '- ' + (0, _jestMatcherUtils.stringify)(expected[i])
  169. ) + ','
  170. );
  171. }
  172. if (i < received.length) {
  173. lines.push(
  174. (0, _jestMatcherUtils.RECEIVED_COLOR)(
  175. '+ ' + (0, _jestMatcherUtils.stringify)(received[i])
  176. ) + ','
  177. );
  178. }
  179. }
  180. return lines.join('\n') + '\n';
  181. }
  182. return expectedLine + label + printReceivedArgs(received, expected) + '\n';
  183. }
  184. const printAligned = getRightAlignedPrinter(label);
  185. return (
  186. expectedLine +
  187. 'Received\n' +
  188. indexedCalls.reduce((printed, [i, received]) => {
  189. const aligned = printAligned(String(i + 1), i === iExpectedCall);
  190. return (
  191. printed +
  192. ((i === iExpectedCall || iExpectedCall === undefined) &&
  193. isLineDiffableCall(expected, received)
  194. ? aligned.replace(': ', '\n') +
  195. printDiffCall(expected, received, expand)
  196. : aligned + printReceivedArgs(received, expected)) +
  197. '\n'
  198. );
  199. }, '')
  200. );
  201. };
  202. const indentation = 'Received'.replace(/\w/g, ' ');
  203. const printDiffCall = (expected, received, expand) =>
  204. received
  205. .map((arg, i) => {
  206. if (i < expected.length) {
  207. if (isEqualValue(expected[i], arg)) {
  208. return indentation + ' ' + printCommon(arg) + ',';
  209. }
  210. if (isLineDiffableArg(expected[i], arg)) {
  211. const difference = (0, _jestMatcherUtils.diff)(expected[i], arg, {
  212. expand
  213. });
  214. if (
  215. typeof difference === 'string' &&
  216. difference.includes('- Expected') &&
  217. difference.includes('+ Received')
  218. ) {
  219. // Display diff with indentation.
  220. return (
  221. difference
  222. .split('\n')
  223. .slice(3)
  224. .map(line => indentation + line)
  225. .join('\n') + ','
  226. );
  227. }
  228. }
  229. } // Display + only if received arg has no corresponding expected arg.
  230. return (
  231. indentation +
  232. (i < expected.length
  233. ? ' ' + (0, _jestMatcherUtils.printReceived)(arg)
  234. : (0, _jestMatcherUtils.RECEIVED_COLOR)(
  235. '+ ' + (0, _jestMatcherUtils.stringify)(arg)
  236. )) +
  237. ','
  238. );
  239. })
  240. .join('\n');
  241. const isLineDiffableCall = (expected, received) =>
  242. expected.some(
  243. (arg, i) => i < received.length && isLineDiffableArg(arg, received[i])
  244. ); // Almost redundant with function in jest-matcher-utils,
  245. // except no line diff for any strings.
  246. const isLineDiffableArg = (expected, received) => {
  247. const expectedType = (0, _jestGetType.default)(expected);
  248. const receivedType = (0, _jestGetType.default)(received);
  249. if (expectedType !== receivedType) {
  250. return false;
  251. }
  252. if ((0, _jestGetType.isPrimitive)(expected)) {
  253. return false;
  254. }
  255. if (
  256. expectedType === 'date' ||
  257. expectedType === 'function' ||
  258. expectedType === 'regexp'
  259. ) {
  260. return false;
  261. }
  262. if (expected instanceof Error && received instanceof Error) {
  263. return false;
  264. }
  265. if (
  266. expectedType === 'object' &&
  267. typeof expected.asymmetricMatch === 'function'
  268. ) {
  269. return false;
  270. }
  271. if (
  272. receivedType === 'object' &&
  273. typeof received.asymmetricMatch === 'function'
  274. ) {
  275. return false;
  276. }
  277. return true;
  278. };
  279. const printResult = (result, expected) =>
  280. result.type === 'throw'
  281. ? 'function call threw an error'
  282. : result.type === 'incomplete'
  283. ? 'function call has not returned yet'
  284. : isEqualValue(expected, result.value)
  285. ? printCommon(result.value)
  286. : (0, _jestMatcherUtils.printReceived)(result.value);
  287. // Return either empty string or one line per indexed result,
  288. // so additional empty line can separate from `Number of returns` which follows.
  289. const printReceivedResults = (
  290. label,
  291. expected,
  292. indexedResults,
  293. isOnlyCall,
  294. iExpectedCall
  295. ) => {
  296. if (indexedResults.length === 0) {
  297. return '';
  298. }
  299. if (isOnlyCall && (iExpectedCall === 0 || iExpectedCall === undefined)) {
  300. return label + printResult(indexedResults[0][1], expected) + '\n';
  301. }
  302. const printAligned = getRightAlignedPrinter(label);
  303. return (
  304. label.replace(':', '').trim() +
  305. '\n' +
  306. indexedResults.reduce(
  307. (printed, [i, result]) =>
  308. printed +
  309. printAligned(String(i + 1), i === iExpectedCall) +
  310. printResult(result, expected) +
  311. '\n',
  312. ''
  313. )
  314. );
  315. };
  316. const createToBeCalledMatcher = matcherName =>
  317. function(received, expected) {
  318. const expectedArgument = '';
  319. const options = {
  320. isNot: this.isNot,
  321. promise: this.promise
  322. };
  323. (0, _jestMatcherUtils.ensureNoExpected)(expected, matcherName, options);
  324. ensureMockOrSpy(received, matcherName, expectedArgument, options);
  325. const receivedIsSpy = isSpy(received);
  326. const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
  327. const count = receivedIsSpy
  328. ? received.calls.count()
  329. : received.mock.calls.length;
  330. const calls = receivedIsSpy
  331. ? received.calls.all().map(x => x.args)
  332. : received.mock.calls;
  333. const pass = count > 0;
  334. const message = pass
  335. ? () =>
  336. (0, _jestMatcherUtils.matcherHint)(
  337. matcherName,
  338. receivedName,
  339. expectedArgument,
  340. options
  341. ) +
  342. '\n\n' +
  343. `Expected number of calls: ${(0, _jestMatcherUtils.printExpected)(
  344. 0
  345. )}\n` +
  346. `Received number of calls: ${(0, _jestMatcherUtils.printReceived)(
  347. count
  348. )}\n\n` +
  349. calls
  350. .reduce((lines, args, i) => {
  351. if (lines.length < PRINT_LIMIT) {
  352. lines.push(`${i + 1}: ${printReceivedArgs(args)}`);
  353. }
  354. return lines;
  355. }, [])
  356. .join('\n')
  357. : () =>
  358. (0, _jestMatcherUtils.matcherHint)(
  359. matcherName,
  360. receivedName,
  361. expectedArgument,
  362. options
  363. ) +
  364. '\n\n' +
  365. `Expected number of calls: >= ${(0, _jestMatcherUtils.printExpected)(
  366. 1
  367. )}\n` +
  368. `Received number of calls: ${(0, _jestMatcherUtils.printReceived)(
  369. count
  370. )}`;
  371. return {
  372. message,
  373. pass
  374. };
  375. };
  376. const createToReturnMatcher = matcherName =>
  377. function(received, expected) {
  378. const expectedArgument = '';
  379. const options = {
  380. isNot: this.isNot,
  381. promise: this.promise
  382. };
  383. (0, _jestMatcherUtils.ensureNoExpected)(expected, matcherName, options);
  384. ensureMock(received, matcherName, expectedArgument, options);
  385. const receivedName = received.getMockName(); // Count return values that correspond only to calls that returned
  386. const count = received.mock.results.reduce(
  387. (n, result) => (result.type === 'return' ? n + 1 : n),
  388. 0
  389. );
  390. const pass = count > 0;
  391. const message = pass
  392. ? () =>
  393. (0, _jestMatcherUtils.matcherHint)(
  394. matcherName,
  395. receivedName,
  396. expectedArgument,
  397. options
  398. ) +
  399. '\n\n' +
  400. `Expected number of returns: ${(0, _jestMatcherUtils.printExpected)(
  401. 0
  402. )}\n` +
  403. `Received number of returns: ${(0, _jestMatcherUtils.printReceived)(
  404. count
  405. )}\n\n` +
  406. received.mock.results
  407. .reduce((lines, result, i) => {
  408. if (result.type === 'return' && lines.length < PRINT_LIMIT) {
  409. lines.push(
  410. `${i + 1}: ${(0, _jestMatcherUtils.printReceived)(
  411. result.value
  412. )}`
  413. );
  414. }
  415. return lines;
  416. }, [])
  417. .join('\n') +
  418. (received.mock.calls.length !== count
  419. ? `\n\nReceived number of calls: ${(0,
  420. _jestMatcherUtils.printReceived)(received.mock.calls.length)}`
  421. : '')
  422. : () =>
  423. (0, _jestMatcherUtils.matcherHint)(
  424. matcherName,
  425. receivedName,
  426. expectedArgument,
  427. options
  428. ) +
  429. '\n\n' +
  430. `Expected number of returns: >= ${(0,
  431. _jestMatcherUtils.printExpected)(1)}\n` +
  432. `Received number of returns: ${(0,
  433. _jestMatcherUtils.printReceived)(count)}` +
  434. (received.mock.calls.length !== count
  435. ? `\nReceived number of calls: ${(0,
  436. _jestMatcherUtils.printReceived)(received.mock.calls.length)}`
  437. : '');
  438. return {
  439. message,
  440. pass
  441. };
  442. };
  443. const createToBeCalledTimesMatcher = matcherName =>
  444. function(received, expected) {
  445. const expectedArgument = 'expected';
  446. const options = {
  447. isNot: this.isNot,
  448. promise: this.promise
  449. };
  450. (0, _jestMatcherUtils.ensureExpectedIsNumber)(
  451. expected,
  452. matcherName,
  453. options
  454. );
  455. ensureMockOrSpy(received, matcherName, expectedArgument, options);
  456. const receivedIsSpy = isSpy(received);
  457. const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
  458. const count = receivedIsSpy
  459. ? received.calls.count()
  460. : received.mock.calls.length;
  461. const pass = count === expected;
  462. const message = pass
  463. ? () =>
  464. (0, _jestMatcherUtils.matcherHint)(
  465. matcherName,
  466. receivedName,
  467. expectedArgument,
  468. options
  469. ) +
  470. `\n\n` +
  471. `Expected number of calls: not ${(0, _jestMatcherUtils.printExpected)(
  472. expected
  473. )}`
  474. : () =>
  475. (0, _jestMatcherUtils.matcherHint)(
  476. matcherName,
  477. receivedName,
  478. expectedArgument,
  479. options
  480. ) +
  481. '\n\n' +
  482. `Expected number of calls: ${(0, _jestMatcherUtils.printExpected)(
  483. expected
  484. )}\n` +
  485. `Received number of calls: ${(0, _jestMatcherUtils.printReceived)(
  486. count
  487. )}`;
  488. return {
  489. message,
  490. pass
  491. };
  492. };
  493. const createToReturnTimesMatcher = matcherName =>
  494. function(received, expected) {
  495. const expectedArgument = 'expected';
  496. const options = {
  497. isNot: this.isNot,
  498. promise: this.promise
  499. };
  500. (0, _jestMatcherUtils.ensureExpectedIsNumber)(
  501. expected,
  502. matcherName,
  503. options
  504. );
  505. ensureMock(received, matcherName, expectedArgument, options);
  506. const receivedName = received.getMockName(); // Count return values that correspond only to calls that returned
  507. const count = received.mock.results.reduce(
  508. (n, result) => (result.type === 'return' ? n + 1 : n),
  509. 0
  510. );
  511. const pass = count === expected;
  512. const message = pass
  513. ? () =>
  514. (0, _jestMatcherUtils.matcherHint)(
  515. matcherName,
  516. receivedName,
  517. expectedArgument,
  518. options
  519. ) +
  520. `\n\n` +
  521. `Expected number of returns: not ${(0,
  522. _jestMatcherUtils.printExpected)(expected)}` +
  523. (received.mock.calls.length !== count
  524. ? `\n\nReceived number of calls: ${(0,
  525. _jestMatcherUtils.printReceived)(received.mock.calls.length)}`
  526. : '')
  527. : () =>
  528. (0, _jestMatcherUtils.matcherHint)(
  529. matcherName,
  530. receivedName,
  531. expectedArgument,
  532. options
  533. ) +
  534. '\n\n' +
  535. `Expected number of returns: ${(0, _jestMatcherUtils.printExpected)(
  536. expected
  537. )}\n` +
  538. `Received number of returns: ${(0, _jestMatcherUtils.printReceived)(
  539. count
  540. )}` +
  541. (received.mock.calls.length !== count
  542. ? `\nReceived number of calls: ${(0,
  543. _jestMatcherUtils.printReceived)(received.mock.calls.length)}`
  544. : '');
  545. return {
  546. message,
  547. pass
  548. };
  549. };
  550. const createToBeCalledWithMatcher = matcherName =>
  551. function(received, ...expected) {
  552. const expectedArgument = '...expected';
  553. const options = {
  554. isNot: this.isNot,
  555. promise: this.promise
  556. };
  557. ensureMockOrSpy(received, matcherName, expectedArgument, options);
  558. const receivedIsSpy = isSpy(received);
  559. const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
  560. const calls = receivedIsSpy
  561. ? received.calls.all().map(x => x.args)
  562. : received.mock.calls;
  563. const pass = calls.some(call => isEqualCall(expected, call));
  564. const message = pass
  565. ? () => {
  566. // Some examples of calls that are equal to expected value.
  567. const indexedCalls = [];
  568. let i = 0;
  569. while (i < calls.length && indexedCalls.length < PRINT_LIMIT) {
  570. if (isEqualCall(expected, calls[i])) {
  571. indexedCalls.push([i, calls[i]]);
  572. }
  573. i += 1;
  574. }
  575. return (
  576. (0, _jestMatcherUtils.matcherHint)(
  577. matcherName,
  578. receivedName,
  579. expectedArgument,
  580. options
  581. ) +
  582. '\n\n' +
  583. `Expected: not ${printExpectedArgs(expected)}\n` +
  584. (calls.length === 1 &&
  585. (0, _jestMatcherUtils.stringify)(calls[0]) ===
  586. (0, _jestMatcherUtils.stringify)(expected)
  587. ? ''
  588. : printReceivedCallsNegative(
  589. expected,
  590. indexedCalls,
  591. calls.length === 1
  592. )) +
  593. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  594. calls.length
  595. )}`
  596. );
  597. }
  598. : () => {
  599. // Some examples of calls that are not equal to expected value.
  600. const indexedCalls = [];
  601. let i = 0;
  602. while (i < calls.length && indexedCalls.length < PRINT_LIMIT) {
  603. indexedCalls.push([i, calls[i]]);
  604. i += 1;
  605. }
  606. return (
  607. (0, _jestMatcherUtils.matcherHint)(
  608. matcherName,
  609. receivedName,
  610. expectedArgument,
  611. options
  612. ) +
  613. '\n\n' +
  614. printExpectedReceivedCallsPositive(
  615. expected,
  616. indexedCalls,
  617. isExpand(this.expand),
  618. calls.length === 1
  619. ) +
  620. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  621. calls.length
  622. )}`
  623. );
  624. };
  625. return {
  626. message,
  627. pass
  628. };
  629. };
  630. const createToReturnWithMatcher = matcherName =>
  631. function(received, expected) {
  632. const expectedArgument = 'expected';
  633. const options = {
  634. isNot: this.isNot,
  635. promise: this.promise
  636. };
  637. ensureMock(received, matcherName, expectedArgument, options);
  638. const receivedName = received.getMockName();
  639. const _received$mock = received.mock,
  640. calls = _received$mock.calls,
  641. results = _received$mock.results;
  642. const pass = results.some(result => isEqualReturn(expected, result));
  643. const message = pass
  644. ? () => {
  645. // Some examples of results that are equal to expected value.
  646. const indexedResults = [];
  647. let i = 0;
  648. while (i < results.length && indexedResults.length < PRINT_LIMIT) {
  649. if (isEqualReturn(expected, results[i])) {
  650. indexedResults.push([i, results[i]]);
  651. }
  652. i += 1;
  653. }
  654. return (
  655. (0, _jestMatcherUtils.matcherHint)(
  656. matcherName,
  657. receivedName,
  658. expectedArgument,
  659. options
  660. ) +
  661. '\n\n' +
  662. `Expected: not ${(0, _jestMatcherUtils.printExpected)(
  663. expected
  664. )}\n` +
  665. (results.length === 1 &&
  666. results[0].type === 'return' &&
  667. (0, _jestMatcherUtils.stringify)(results[0].value) ===
  668. (0, _jestMatcherUtils.stringify)(expected)
  669. ? ''
  670. : printReceivedResults(
  671. 'Received: ',
  672. expected,
  673. indexedResults,
  674. results.length === 1
  675. )) +
  676. printNumberOfReturns(countReturns(results), calls.length)
  677. );
  678. }
  679. : () => {
  680. // Some examples of results that are not equal to expected value.
  681. const indexedResults = [];
  682. let i = 0;
  683. while (i < results.length && indexedResults.length < PRINT_LIMIT) {
  684. indexedResults.push([i, results[i]]);
  685. i += 1;
  686. }
  687. return (
  688. (0, _jestMatcherUtils.matcherHint)(
  689. matcherName,
  690. receivedName,
  691. expectedArgument,
  692. options
  693. ) +
  694. '\n\n' +
  695. `Expected: ${(0, _jestMatcherUtils.printExpected)(expected)}\n` +
  696. printReceivedResults(
  697. 'Received: ',
  698. expected,
  699. indexedResults,
  700. results.length === 1
  701. ) +
  702. printNumberOfReturns(countReturns(results), calls.length)
  703. );
  704. };
  705. return {
  706. message,
  707. pass
  708. };
  709. };
  710. const createLastCalledWithMatcher = matcherName =>
  711. function(received, ...expected) {
  712. const expectedArgument = '...expected';
  713. const options = {
  714. isNot: this.isNot,
  715. promise: this.promise
  716. };
  717. ensureMockOrSpy(received, matcherName, expectedArgument, options);
  718. const receivedIsSpy = isSpy(received);
  719. const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
  720. const calls = receivedIsSpy
  721. ? received.calls.all().map(x => x.args)
  722. : received.mock.calls;
  723. const iLast = calls.length - 1;
  724. const pass = iLast >= 0 && isEqualCall(expected, calls[iLast]);
  725. const message = pass
  726. ? () => {
  727. const indexedCalls = [];
  728. if (iLast > 0) {
  729. // Display preceding call as context.
  730. indexedCalls.push([iLast - 1, calls[iLast - 1]]);
  731. }
  732. indexedCalls.push([iLast, calls[iLast]]);
  733. return (
  734. (0, _jestMatcherUtils.matcherHint)(
  735. matcherName,
  736. receivedName,
  737. expectedArgument,
  738. options
  739. ) +
  740. '\n\n' +
  741. `Expected: not ${printExpectedArgs(expected)}\n` +
  742. (calls.length === 1 &&
  743. (0, _jestMatcherUtils.stringify)(calls[0]) ===
  744. (0, _jestMatcherUtils.stringify)(expected)
  745. ? ''
  746. : printReceivedCallsNegative(
  747. expected,
  748. indexedCalls,
  749. calls.length === 1,
  750. iLast
  751. )) +
  752. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  753. calls.length
  754. )}`
  755. );
  756. }
  757. : () => {
  758. const indexedCalls = [];
  759. if (iLast >= 0) {
  760. if (iLast > 0) {
  761. let i = iLast - 1; // Is there a preceding call that is equal to expected args?
  762. while (i >= 0 && !isEqualCall(expected, calls[i])) {
  763. i -= 1;
  764. }
  765. if (i < 0) {
  766. i = iLast - 1; // otherwise, preceding call
  767. }
  768. indexedCalls.push([i, calls[i]]);
  769. }
  770. indexedCalls.push([iLast, calls[iLast]]);
  771. }
  772. return (
  773. (0, _jestMatcherUtils.matcherHint)(
  774. matcherName,
  775. receivedName,
  776. expectedArgument,
  777. options
  778. ) +
  779. '\n\n' +
  780. printExpectedReceivedCallsPositive(
  781. expected,
  782. indexedCalls,
  783. isExpand(this.expand),
  784. calls.length === 1,
  785. iLast
  786. ) +
  787. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  788. calls.length
  789. )}`
  790. );
  791. };
  792. return {
  793. message,
  794. pass
  795. };
  796. };
  797. const createLastReturnedMatcher = matcherName =>
  798. function(received, expected) {
  799. const expectedArgument = 'expected';
  800. const options = {
  801. isNot: this.isNot,
  802. promise: this.promise
  803. };
  804. ensureMock(received, matcherName, expectedArgument, options);
  805. const receivedName = received.getMockName();
  806. const _received$mock2 = received.mock,
  807. calls = _received$mock2.calls,
  808. results = _received$mock2.results;
  809. const iLast = results.length - 1;
  810. const pass = iLast >= 0 && isEqualReturn(expected, results[iLast]);
  811. const message = pass
  812. ? () => {
  813. const indexedResults = [];
  814. if (iLast > 0) {
  815. // Display preceding result as context.
  816. indexedResults.push([iLast - 1, results[iLast - 1]]);
  817. }
  818. indexedResults.push([iLast, results[iLast]]);
  819. return (
  820. (0, _jestMatcherUtils.matcherHint)(
  821. matcherName,
  822. receivedName,
  823. expectedArgument,
  824. options
  825. ) +
  826. '\n\n' +
  827. `Expected: not ${(0, _jestMatcherUtils.printExpected)(
  828. expected
  829. )}\n` +
  830. (results.length === 1 &&
  831. results[0].type === 'return' &&
  832. (0, _jestMatcherUtils.stringify)(results[0].value) ===
  833. (0, _jestMatcherUtils.stringify)(expected)
  834. ? ''
  835. : printReceivedResults(
  836. 'Received: ',
  837. expected,
  838. indexedResults,
  839. results.length === 1,
  840. iLast
  841. )) +
  842. printNumberOfReturns(countReturns(results), calls.length)
  843. );
  844. }
  845. : () => {
  846. const indexedResults = [];
  847. if (iLast >= 0) {
  848. if (iLast > 0) {
  849. let i = iLast - 1; // Is there a preceding result that is equal to expected value?
  850. while (i >= 0 && !isEqualReturn(expected, results[i])) {
  851. i -= 1;
  852. }
  853. if (i < 0) {
  854. i = iLast - 1; // otherwise, preceding result
  855. }
  856. indexedResults.push([i, results[i]]);
  857. }
  858. indexedResults.push([iLast, results[iLast]]);
  859. }
  860. return (
  861. (0, _jestMatcherUtils.matcherHint)(
  862. matcherName,
  863. receivedName,
  864. expectedArgument,
  865. options
  866. ) +
  867. '\n\n' +
  868. `Expected: ${(0, _jestMatcherUtils.printExpected)(expected)}\n` +
  869. printReceivedResults(
  870. 'Received: ',
  871. expected,
  872. indexedResults,
  873. results.length === 1,
  874. iLast
  875. ) +
  876. printNumberOfReturns(countReturns(results), calls.length)
  877. );
  878. };
  879. return {
  880. message,
  881. pass
  882. };
  883. };
  884. const createNthCalledWithMatcher = matcherName =>
  885. function(received, nth, ...expected) {
  886. const expectedArgument = 'n';
  887. const options = {
  888. expectedColor: arg => arg,
  889. isNot: this.isNot,
  890. promise: this.promise,
  891. secondArgument: '...expected'
  892. };
  893. ensureMockOrSpy(received, matcherName, expectedArgument, options);
  894. if (!Number.isSafeInteger(nth) || nth < 1) {
  895. throw new Error(
  896. (0, _jestMatcherUtils.matcherErrorMessage)(
  897. (0, _jestMatcherUtils.matcherHint)(
  898. matcherName,
  899. undefined,
  900. expectedArgument,
  901. options
  902. ),
  903. `${expectedArgument} must be a positive integer`,
  904. (0, _jestMatcherUtils.printWithType)(
  905. expectedArgument,
  906. nth,
  907. _jestMatcherUtils.stringify
  908. )
  909. )
  910. );
  911. }
  912. const receivedIsSpy = isSpy(received);
  913. const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
  914. const calls = receivedIsSpy
  915. ? received.calls.all().map(x => x.args)
  916. : received.mock.calls;
  917. const length = calls.length;
  918. const iNth = nth - 1;
  919. const pass = iNth < length && isEqualCall(expected, calls[iNth]);
  920. const message = pass
  921. ? () => {
  922. // Display preceding and following calls,
  923. const indexedCalls = [];
  924. if (iNth - 1 >= 0) {
  925. indexedCalls.push([iNth - 1, calls[iNth - 1]]);
  926. }
  927. indexedCalls.push([iNth, calls[iNth]]);
  928. if (iNth + 1 < length) {
  929. indexedCalls.push([iNth + 1, calls[iNth + 1]]);
  930. }
  931. return (
  932. (0, _jestMatcherUtils.matcherHint)(
  933. matcherName,
  934. receivedName,
  935. expectedArgument,
  936. options
  937. ) +
  938. '\n\n' +
  939. `n: ${nth}\n` +
  940. `Expected: not ${printExpectedArgs(expected)}\n` +
  941. (calls.length === 1 &&
  942. (0, _jestMatcherUtils.stringify)(calls[0]) ===
  943. (0, _jestMatcherUtils.stringify)(expected)
  944. ? ''
  945. : printReceivedCallsNegative(
  946. expected,
  947. indexedCalls,
  948. calls.length === 1,
  949. iNth
  950. )) +
  951. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  952. calls.length
  953. )}`
  954. );
  955. }
  956. : () => {
  957. // Display preceding and following calls:
  958. // * nearest call that is equal to expected args
  959. // * otherwise, adjacent call
  960. const indexedCalls = [];
  961. if (iNth < length) {
  962. if (iNth - 1 >= 0) {
  963. let i = iNth - 1; // Is there a preceding call that is equal to expected args?
  964. while (i >= 0 && !isEqualCall(expected, calls[i])) {
  965. i -= 1;
  966. }
  967. if (i < 0) {
  968. i = iNth - 1; // otherwise, adjacent call
  969. }
  970. indexedCalls.push([i, calls[i]]);
  971. }
  972. indexedCalls.push([iNth, calls[iNth]]);
  973. if (iNth + 1 < length) {
  974. let i = iNth + 1; // Is there a following call that is equal to expected args?
  975. while (i < length && !isEqualCall(expected, calls[i])) {
  976. i += 1;
  977. }
  978. if (i >= length) {
  979. i = iNth + 1; // otherwise, adjacent call
  980. }
  981. indexedCalls.push([i, calls[i]]);
  982. }
  983. } else if (length > 0) {
  984. // The number of received calls is fewer than the expected number.
  985. let i = length - 1; // Is there a call that is equal to expected args?
  986. while (i >= 0 && !isEqualCall(expected, calls[i])) {
  987. i -= 1;
  988. }
  989. if (i < 0) {
  990. i = length - 1; // otherwise, last call
  991. }
  992. indexedCalls.push([i, calls[i]]);
  993. }
  994. return (
  995. (0, _jestMatcherUtils.matcherHint)(
  996. matcherName,
  997. receivedName,
  998. expectedArgument,
  999. options
  1000. ) +
  1001. '\n\n' +
  1002. `n: ${nth}\n` +
  1003. printExpectedReceivedCallsPositive(
  1004. expected,
  1005. indexedCalls,
  1006. isExpand(this.expand),
  1007. calls.length === 1,
  1008. iNth
  1009. ) +
  1010. `\nNumber of calls: ${(0, _jestMatcherUtils.printReceived)(
  1011. calls.length
  1012. )}`
  1013. );
  1014. };
  1015. return {
  1016. message,
  1017. pass
  1018. };
  1019. };
  1020. const createNthReturnedWithMatcher = matcherName =>
  1021. function(received, nth, expected) {
  1022. const expectedArgument = 'n';
  1023. const options = {
  1024. expectedColor: arg => arg,
  1025. isNot: this.isNot,
  1026. promise: this.promise,
  1027. secondArgument: 'expected'
  1028. };
  1029. ensureMock(received, matcherName, expectedArgument, options);
  1030. if (!Number.isSafeInteger(nth) || nth < 1) {
  1031. throw new Error(
  1032. (0, _jestMatcherUtils.matcherErrorMessage)(
  1033. (0, _jestMatcherUtils.matcherHint)(
  1034. matcherName,
  1035. undefined,
  1036. expectedArgument,
  1037. options
  1038. ),
  1039. `${expectedArgument} must be a positive integer`,
  1040. (0, _jestMatcherUtils.printWithType)(
  1041. expectedArgument,
  1042. nth,
  1043. _jestMatcherUtils.stringify
  1044. )
  1045. )
  1046. );
  1047. }
  1048. const receivedName = received.getMockName();
  1049. const _received$mock3 = received.mock,
  1050. calls = _received$mock3.calls,
  1051. results = _received$mock3.results;
  1052. const length = results.length;
  1053. const iNth = nth - 1;
  1054. const pass = iNth < length && isEqualReturn(expected, results[iNth]);
  1055. const message = pass
  1056. ? () => {
  1057. // Display preceding and following results,
  1058. const indexedResults = [];
  1059. if (iNth - 1 >= 0) {
  1060. indexedResults.push([iNth - 1, results[iNth - 1]]);
  1061. }
  1062. indexedResults.push([iNth, results[iNth]]);
  1063. if (iNth + 1 < length) {
  1064. indexedResults.push([iNth + 1, results[iNth + 1]]);
  1065. }
  1066. return (
  1067. (0, _jestMatcherUtils.matcherHint)(
  1068. matcherName,
  1069. receivedName,
  1070. expectedArgument,
  1071. options
  1072. ) +
  1073. '\n\n' +
  1074. `n: ${nth}\n` +
  1075. `Expected: not ${(0, _jestMatcherUtils.printExpected)(
  1076. expected
  1077. )}\n` +
  1078. (results.length === 1 &&
  1079. results[0].type === 'return' &&
  1080. (0, _jestMatcherUtils.stringify)(results[0].value) ===
  1081. (0, _jestMatcherUtils.stringify)(expected)
  1082. ? ''
  1083. : printReceivedResults(
  1084. 'Received: ',
  1085. expected,
  1086. indexedResults,
  1087. results.length === 1,
  1088. iNth
  1089. )) +
  1090. printNumberOfReturns(countReturns(results), calls.length)
  1091. );
  1092. }
  1093. : () => {
  1094. // Display preceding and following results:
  1095. // * nearest result that is equal to expected value
  1096. // * otherwise, adjacent result
  1097. const indexedResults = [];
  1098. if (iNth < length) {
  1099. if (iNth - 1 >= 0) {
  1100. let i = iNth - 1; // Is there a preceding result that is equal to expected value?
  1101. while (i >= 0 && !isEqualReturn(expected, results[i])) {
  1102. i -= 1;
  1103. }
  1104. if (i < 0) {
  1105. i = iNth - 1; // otherwise, adjacent result
  1106. }
  1107. indexedResults.push([i, results[i]]);
  1108. }
  1109. indexedResults.push([iNth, results[iNth]]);
  1110. if (iNth + 1 < length) {
  1111. let i = iNth + 1; // Is there a following result that is equal to expected value?
  1112. while (i < length && !isEqualReturn(expected, results[i])) {
  1113. i += 1;
  1114. }
  1115. if (i >= length) {
  1116. i = iNth + 1; // otherwise, adjacent result
  1117. }
  1118. indexedResults.push([i, results[i]]);
  1119. }
  1120. } else if (length > 0) {
  1121. // The number of received calls is fewer than the expected number.
  1122. let i = length - 1; // Is there a result that is equal to expected value?
  1123. while (i >= 0 && !isEqualReturn(expected, results[i])) {
  1124. i -= 1;
  1125. }
  1126. if (i < 0) {
  1127. i = length - 1; // otherwise, last result
  1128. }
  1129. indexedResults.push([i, results[i]]);
  1130. }
  1131. return (
  1132. (0, _jestMatcherUtils.matcherHint)(
  1133. matcherName,
  1134. receivedName,
  1135. expectedArgument,
  1136. options
  1137. ) +
  1138. '\n\n' +
  1139. `n: ${nth}\n` +
  1140. `Expected: ${(0, _jestMatcherUtils.printExpected)(expected)}\n` +
  1141. printReceivedResults(
  1142. 'Received: ',
  1143. expected,
  1144. indexedResults,
  1145. results.length === 1,
  1146. iNth
  1147. ) +
  1148. printNumberOfReturns(countReturns(results), calls.length)
  1149. );
  1150. };
  1151. return {
  1152. message,
  1153. pass
  1154. };
  1155. };
  1156. const spyMatchers = {
  1157. lastCalledWith: createLastCalledWithMatcher('lastCalledWith'),
  1158. lastReturnedWith: createLastReturnedMatcher('lastReturnedWith'),
  1159. nthCalledWith: createNthCalledWithMatcher('nthCalledWith'),
  1160. nthReturnedWith: createNthReturnedWithMatcher('nthReturnedWith'),
  1161. toBeCalled: createToBeCalledMatcher('toBeCalled'),
  1162. toBeCalledTimes: createToBeCalledTimesMatcher('toBeCalledTimes'),
  1163. toBeCalledWith: createToBeCalledWithMatcher('toBeCalledWith'),
  1164. toHaveBeenCalled: createToBeCalledMatcher('toHaveBeenCalled'),
  1165. toHaveBeenCalledTimes: createToBeCalledTimesMatcher('toHaveBeenCalledTimes'),
  1166. toHaveBeenCalledWith: createToBeCalledWithMatcher('toHaveBeenCalledWith'),
  1167. toHaveBeenLastCalledWith: createLastCalledWithMatcher(
  1168. 'toHaveBeenLastCalledWith'
  1169. ),
  1170. toHaveBeenNthCalledWith: createNthCalledWithMatcher(
  1171. 'toHaveBeenNthCalledWith'
  1172. ),
  1173. toHaveLastReturnedWith: createLastReturnedMatcher('toHaveLastReturnedWith'),
  1174. toHaveNthReturnedWith: createNthReturnedWithMatcher('toHaveNthReturnedWith'),
  1175. toHaveReturned: createToReturnMatcher('toHaveReturned'),
  1176. toHaveReturnedTimes: createToReturnTimesMatcher('toHaveReturnedTimes'),
  1177. toHaveReturnedWith: createToReturnWithMatcher('toHaveReturnedWith'),
  1178. toReturn: createToReturnMatcher('toReturn'),
  1179. toReturnTimes: createToReturnTimesMatcher('toReturnTimes'),
  1180. toReturnWith: createToReturnWithMatcher('toReturnWith')
  1181. };
  1182. const isMock = received =>
  1183. received != null && received._isMockFunction === true;
  1184. const isSpy = received =>
  1185. received != null &&
  1186. received.calls != null &&
  1187. typeof received.calls.all === 'function' &&
  1188. typeof received.calls.count === 'function';
  1189. const ensureMockOrSpy = (received, matcherName, expectedArgument, options) => {
  1190. if (!isMock(received) && !isSpy(received)) {
  1191. throw new Error(
  1192. (0, _jestMatcherUtils.matcherErrorMessage)(
  1193. (0, _jestMatcherUtils.matcherHint)(
  1194. matcherName,
  1195. undefined,
  1196. expectedArgument,
  1197. options
  1198. ),
  1199. `${(0, _jestMatcherUtils.RECEIVED_COLOR)(
  1200. 'received'
  1201. )} value must be a mock or spy function`,
  1202. (0, _jestMatcherUtils.printWithType)(
  1203. 'Received',
  1204. received,
  1205. _jestMatcherUtils.printReceived
  1206. )
  1207. )
  1208. );
  1209. }
  1210. };
  1211. const ensureMock = (received, matcherName, expectedArgument, options) => {
  1212. if (!isMock(received)) {
  1213. throw new Error(
  1214. (0, _jestMatcherUtils.matcherErrorMessage)(
  1215. (0, _jestMatcherUtils.matcherHint)(
  1216. matcherName,
  1217. undefined,
  1218. expectedArgument,
  1219. options
  1220. ),
  1221. `${(0, _jestMatcherUtils.RECEIVED_COLOR)(
  1222. 'received'
  1223. )} value must be a mock function`,
  1224. (0, _jestMatcherUtils.printWithType)(
  1225. 'Received',
  1226. received,
  1227. _jestMatcherUtils.printReceived
  1228. )
  1229. )
  1230. );
  1231. }
  1232. };
  1233. var _default = spyMatchers;
  1234. exports.default = _default;