index.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. 'use strict';
  2. var _prettyFormat = require('pretty-format');
  3. var _prettyFormat2 = _interopRequireDefault(_prettyFormat);
  4. var _chalk = require('chalk');
  5. var _chalk2 = _interopRequireDefault(_chalk);
  6. var _jestGetType = require('jest-get-type');
  7. var _jestGetType2 = _interopRequireDefault(_jestGetType);
  8. var _diff_strings = require('./diff_strings');
  9. var _diff_strings2 = _interopRequireDefault(_diff_strings);
  10. var _constants = require('./constants');
  11. function _interopRequireDefault(obj) {
  12. return obj && obj.__esModule ? obj : {default: obj};
  13. }
  14. /**
  15. * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  16. *
  17. * This source code is licensed under the MIT license found in the
  18. * LICENSE file in the root directory of this source tree.
  19. *
  20. *
  21. */
  22. var _prettyFormat$plugins = _prettyFormat2.default.plugins;
  23. const AsymmetricMatcher = _prettyFormat$plugins.AsymmetricMatcher,
  24. DOMCollection = _prettyFormat$plugins.DOMCollection,
  25. DOMElement = _prettyFormat$plugins.DOMElement,
  26. Immutable = _prettyFormat$plugins.Immutable,
  27. ReactElement = _prettyFormat$plugins.ReactElement,
  28. ReactTestComponent = _prettyFormat$plugins.ReactTestComponent;
  29. const PLUGINS = [
  30. ReactTestComponent,
  31. ReactElement,
  32. DOMElement,
  33. DOMCollection,
  34. Immutable,
  35. AsymmetricMatcher
  36. ];
  37. const FORMAT_OPTIONS = {
  38. plugins: PLUGINS
  39. };
  40. const FORMAT_OPTIONS_0 = Object.assign({}, FORMAT_OPTIONS, {
  41. indent: 0
  42. });
  43. const FALLBACK_FORMAT_OPTIONS = {
  44. callToJSON: false,
  45. maxDepth: 10,
  46. plugins: PLUGINS
  47. };
  48. const FALLBACK_FORMAT_OPTIONS_0 = Object.assign({}, FALLBACK_FORMAT_OPTIONS, {
  49. indent: 0
  50. });
  51. // Generate a string that will highlight the difference between two values
  52. // with green and red. (similar to how github does code diffing)
  53. function diff(a, b, options) {
  54. if (a === b) {
  55. return _constants.NO_DIFF_MESSAGE;
  56. }
  57. const aType = (0, _jestGetType2.default)(a);
  58. let expectedType = aType;
  59. let omitDifference = false;
  60. if (aType === 'object' && typeof a.asymmetricMatch === 'function') {
  61. if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {
  62. // Do not know expected type of user-defined asymmetric matcher.
  63. return null;
  64. }
  65. if (typeof a.getExpectedType !== 'function') {
  66. // For example, expect.anything() matches either null or undefined
  67. return null;
  68. }
  69. expectedType = a.getExpectedType();
  70. // Primitive types boolean and number omit difference below.
  71. // For example, omit difference for expect.stringMatching(regexp)
  72. omitDifference = expectedType === 'string';
  73. }
  74. if (expectedType !== (0, _jestGetType2.default)(b)) {
  75. return (
  76. ' Comparing two different types of values.' +
  77. ` Expected ${_chalk2.default.green(expectedType)} but ` +
  78. `received ${_chalk2.default.red((0, _jestGetType2.default)(b))}.`
  79. );
  80. }
  81. if (omitDifference) {
  82. return null;
  83. }
  84. switch (aType) {
  85. case 'string':
  86. return (0, _diff_strings2.default)(a, b, options);
  87. case 'number':
  88. case 'boolean':
  89. return null;
  90. case 'map':
  91. return compareObjects(sortMap(a), sortMap(b), options);
  92. case 'set':
  93. return compareObjects(sortSet(a), sortSet(b), options);
  94. default:
  95. return compareObjects(a, b, options);
  96. }
  97. }
  98. function sortMap(map) {
  99. return new Map(Array.from(map.entries()).sort());
  100. }
  101. function sortSet(set) {
  102. return new Set(Array.from(set.values()).sort());
  103. }
  104. function compareObjects(a, b, options) {
  105. let diffMessage;
  106. let hasThrown = false;
  107. try {
  108. diffMessage = (0, _diff_strings2.default)(
  109. (0, _prettyFormat2.default)(a, FORMAT_OPTIONS_0),
  110. (0, _prettyFormat2.default)(b, FORMAT_OPTIONS_0),
  111. options,
  112. {
  113. a: (0, _prettyFormat2.default)(a, FORMAT_OPTIONS),
  114. b: (0, _prettyFormat2.default)(b, FORMAT_OPTIONS)
  115. }
  116. );
  117. } catch (e) {
  118. hasThrown = true;
  119. }
  120. // If the comparison yields no results, compare again but this time
  121. // without calling `toJSON`. It's also possible that toJSON might throw.
  122. if (!diffMessage || diffMessage === _constants.NO_DIFF_MESSAGE) {
  123. diffMessage = (0, _diff_strings2.default)(
  124. (0, _prettyFormat2.default)(a, FALLBACK_FORMAT_OPTIONS_0),
  125. (0, _prettyFormat2.default)(b, FALLBACK_FORMAT_OPTIONS_0),
  126. options,
  127. {
  128. a: (0, _prettyFormat2.default)(a, FALLBACK_FORMAT_OPTIONS),
  129. b: (0, _prettyFormat2.default)(b, FALLBACK_FORMAT_OPTIONS)
  130. }
  131. );
  132. if (diffMessage !== _constants.NO_DIFF_MESSAGE && !hasThrown) {
  133. diffMessage = _constants.SIMILAR_MESSAGE + '\n\n' + diffMessage;
  134. }
  135. }
  136. return diffMessage;
  137. }
  138. module.exports = diff;