index.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. 'use strict';
  2. var _prettyFormat = _interopRequireDefault(require('pretty-format'));
  3. var _chalk = _interopRequireDefault(require('chalk'));
  4. var _jestGetType = _interopRequireDefault(require('jest-get-type'));
  5. var _diffLines = _interopRequireDefault(require('./diffLines'));
  6. var _printDiffs = require('./printDiffs');
  7. var _constants = require('./constants');
  8. function _interopRequireDefault(obj) {
  9. return obj && obj.__esModule ? obj : {default: obj};
  10. }
  11. var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
  12. function _objectSpread(target) {
  13. for (var i = 1; i < arguments.length; i++) {
  14. var source = arguments[i] != null ? arguments[i] : {};
  15. var ownKeys = Object.keys(source);
  16. if (typeof Object.getOwnPropertySymbols === 'function') {
  17. ownKeys = ownKeys.concat(
  18. Object.getOwnPropertySymbols(source).filter(function(sym) {
  19. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  20. })
  21. );
  22. }
  23. ownKeys.forEach(function(key) {
  24. _defineProperty(target, key, source[key]);
  25. });
  26. }
  27. return target;
  28. }
  29. function _defineProperty(obj, key, value) {
  30. if (key in obj) {
  31. Object.defineProperty(obj, key, {
  32. value: value,
  33. enumerable: true,
  34. configurable: true,
  35. writable: true
  36. });
  37. } else {
  38. obj[key] = value;
  39. }
  40. return obj;
  41. }
  42. const _prettyFormat$plugins = _prettyFormat.default.plugins,
  43. AsymmetricMatcher = _prettyFormat$plugins.AsymmetricMatcher,
  44. DOMCollection = _prettyFormat$plugins.DOMCollection,
  45. DOMElement = _prettyFormat$plugins.DOMElement,
  46. Immutable = _prettyFormat$plugins.Immutable,
  47. ReactElement = _prettyFormat$plugins.ReactElement,
  48. ReactTestComponent = _prettyFormat$plugins.ReactTestComponent;
  49. const PLUGINS = [
  50. ReactTestComponent,
  51. ReactElement,
  52. DOMElement,
  53. DOMCollection,
  54. Immutable,
  55. AsymmetricMatcher
  56. ];
  57. const FORMAT_OPTIONS = {
  58. plugins: PLUGINS
  59. };
  60. const FORMAT_OPTIONS_0 = _objectSpread({}, FORMAT_OPTIONS, {
  61. indent: 0
  62. });
  63. const FALLBACK_FORMAT_OPTIONS = {
  64. callToJSON: false,
  65. maxDepth: 10,
  66. plugins: PLUGINS
  67. };
  68. const FALLBACK_FORMAT_OPTIONS_0 = _objectSpread({}, FALLBACK_FORMAT_OPTIONS, {
  69. indent: 0
  70. }); // Generate a string that will highlight the difference between two values
  71. // with green and red. (similar to how github does code diffing)
  72. function diff(a, b, options) {
  73. if (Object.is(a, b)) {
  74. return _constants.NO_DIFF_MESSAGE;
  75. }
  76. const aType = (0, _jestGetType.default)(a);
  77. let expectedType = aType;
  78. let omitDifference = false;
  79. if (aType === 'object' && typeof a.asymmetricMatch === 'function') {
  80. if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {
  81. // Do not know expected type of user-defined asymmetric matcher.
  82. return null;
  83. }
  84. if (typeof a.getExpectedType !== 'function') {
  85. // For example, expect.anything() matches either null or undefined
  86. return null;
  87. }
  88. expectedType = a.getExpectedType(); // Primitive types boolean and number omit difference below.
  89. // For example, omit difference for expect.stringMatching(regexp)
  90. omitDifference = expectedType === 'string';
  91. }
  92. if (expectedType !== (0, _jestGetType.default)(b)) {
  93. return (
  94. ' Comparing two different types of values.' +
  95. ` Expected ${_chalk.default.green(expectedType)} but ` +
  96. `received ${_chalk.default.red((0, _jestGetType.default)(b))}.`
  97. );
  98. }
  99. if (omitDifference) {
  100. return null;
  101. }
  102. switch (aType) {
  103. case 'string':
  104. return (0, _diffLines.default)(a, b, options);
  105. case 'boolean':
  106. case 'number':
  107. return comparePrimitive(a, b, options);
  108. case 'map':
  109. return compareObjects(sortMap(a), sortMap(b), options);
  110. case 'set':
  111. return compareObjects(sortSet(a), sortSet(b), options);
  112. default:
  113. return compareObjects(a, b, options);
  114. }
  115. }
  116. function comparePrimitive(a, b, options) {
  117. return (0, _diffLines.default)(
  118. (0, _prettyFormat.default)(a, FORMAT_OPTIONS),
  119. (0, _prettyFormat.default)(b, FORMAT_OPTIONS),
  120. options
  121. );
  122. }
  123. function sortMap(map) {
  124. return new Map(Array.from(map.entries()).sort());
  125. }
  126. function sortSet(set) {
  127. return new Set(Array.from(set.values()).sort());
  128. }
  129. function compareObjects(a, b, options) {
  130. let diffMessage;
  131. let hasThrown = false;
  132. try {
  133. diffMessage = (0, _diffLines.default)(
  134. (0, _prettyFormat.default)(a, FORMAT_OPTIONS_0),
  135. (0, _prettyFormat.default)(b, FORMAT_OPTIONS_0),
  136. options,
  137. {
  138. a: (0, _prettyFormat.default)(a, FORMAT_OPTIONS),
  139. b: (0, _prettyFormat.default)(b, FORMAT_OPTIONS)
  140. }
  141. );
  142. } catch (e) {
  143. hasThrown = true;
  144. } // If the comparison yields no results, compare again but this time
  145. // without calling `toJSON`. It's also possible that toJSON might throw.
  146. if (!diffMessage || diffMessage === _constants.NO_DIFF_MESSAGE) {
  147. diffMessage = (0, _diffLines.default)(
  148. (0, _prettyFormat.default)(a, FALLBACK_FORMAT_OPTIONS_0),
  149. (0, _prettyFormat.default)(b, FALLBACK_FORMAT_OPTIONS_0),
  150. options,
  151. {
  152. a: (0, _prettyFormat.default)(a, FALLBACK_FORMAT_OPTIONS),
  153. b: (0, _prettyFormat.default)(b, FALLBACK_FORMAT_OPTIONS)
  154. }
  155. );
  156. if (diffMessage !== _constants.NO_DIFF_MESSAGE && !hasThrown) {
  157. diffMessage = _constants.SIMILAR_MESSAGE + '\n\n' + diffMessage;
  158. }
  159. }
  160. return diffMessage;
  161. } // eslint-disable-next-line no-redeclare
  162. diff.getStringDiff = _printDiffs.getStringDiff;
  163. module.exports = diff;