index.js
  1  'use strict';
  2  
  3  Object.defineProperty(exports, '__esModule', {
  4    value: true
  5  });
  6  Object.defineProperty(exports, 'DIFF_DELETE', {
  7    enumerable: true,
  8    get: function () {
  9      return _cleanupSemantic.DIFF_DELETE;
 10    }
 11  });
 12  Object.defineProperty(exports, 'DIFF_EQUAL', {
 13    enumerable: true,
 14    get: function () {
 15      return _cleanupSemantic.DIFF_EQUAL;
 16    }
 17  });
 18  Object.defineProperty(exports, 'DIFF_INSERT', {
 19    enumerable: true,
 20    get: function () {
 21      return _cleanupSemantic.DIFF_INSERT;
 22    }
 23  });
 24  Object.defineProperty(exports, 'Diff', {
 25    enumerable: true,
 26    get: function () {
 27      return _cleanupSemantic.Diff;
 28    }
 29  });
 30  Object.defineProperty(exports, 'diffLinesRaw', {
 31    enumerable: true,
 32    get: function () {
 33      return _diffLines.diffLinesRaw;
 34    }
 35  });
 36  Object.defineProperty(exports, 'diffLinesUnified', {
 37    enumerable: true,
 38    get: function () {
 39      return _diffLines.diffLinesUnified;
 40    }
 41  });
 42  Object.defineProperty(exports, 'diffLinesUnified2', {
 43    enumerable: true,
 44    get: function () {
 45      return _diffLines.diffLinesUnified2;
 46    }
 47  });
 48  Object.defineProperty(exports, 'diffStringsRaw', {
 49    enumerable: true,
 50    get: function () {
 51      return _printDiffs.diffStringsRaw;
 52    }
 53  });
 54  Object.defineProperty(exports, 'diffStringsUnified', {
 55    enumerable: true,
 56    get: function () {
 57      return _printDiffs.diffStringsUnified;
 58    }
 59  });
 60  exports.default = void 0;
 61  
 62  var _chalk = _interopRequireDefault(require('chalk'));
 63  
 64  var _jestGetType = _interopRequireDefault(require('jest-get-type'));
 65  
 66  var _prettyFormat = _interopRequireDefault(require('pretty-format'));
 67  
 68  var _cleanupSemantic = require('./cleanupSemantic');
 69  
 70  var _constants = require('./constants');
 71  
 72  var _diffLines = require('./diffLines');
 73  
 74  var _normalizeDiffOptions = require('./normalizeDiffOptions');
 75  
 76  var _printDiffs = require('./printDiffs');
 77  
 78  function _interopRequireDefault(obj) {
 79    return obj && obj.__esModule ? obj : {default: obj};
 80  }
 81  
 82  var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
 83  
 84  const getCommonMessage = (message, options) => {
 85    const {commonColor} = (0, _normalizeDiffOptions.normalizeDiffOptions)(
 86      options
 87    );
 88    return commonColor(message);
 89  };
 90  
 91  const {
 92    AsymmetricMatcher,
 93    DOMCollection,
 94    DOMElement,
 95    Immutable,
 96    ReactElement,
 97    ReactTestComponent
 98  } = _prettyFormat.default.plugins;
 99  const PLUGINS = [
100    ReactTestComponent,
101    ReactElement,
102    DOMElement,
103    DOMCollection,
104    Immutable,
105    AsymmetricMatcher
106  ];
107  const FORMAT_OPTIONS = {
108    plugins: PLUGINS
109  };
110  const FORMAT_OPTIONS_0 = {...FORMAT_OPTIONS, indent: 0};
111  const FALLBACK_FORMAT_OPTIONS = {
112    callToJSON: false,
113    maxDepth: 10,
114    plugins: PLUGINS
115  };
116  const FALLBACK_FORMAT_OPTIONS_0 = {...FALLBACK_FORMAT_OPTIONS, indent: 0}; // Generate a string that will highlight the difference between two values
117  // with green and red. (similar to how github does code diffing)
118  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
119  
120  function diff(a, b, options) {
121    if (Object.is(a, b)) {
122      return getCommonMessage(_constants.NO_DIFF_MESSAGE, options);
123    }
124  
125    const aType = (0, _jestGetType.default)(a);
126    let expectedType = aType;
127    let omitDifference = false;
128  
129    if (aType === 'object' && typeof a.asymmetricMatch === 'function') {
130      if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {
131        // Do not know expected type of user-defined asymmetric matcher.
132        return null;
133      }
134  
135      if (typeof a.getExpectedType !== 'function') {
136        // For example, expect.anything() matches either null or undefined
137        return null;
138      }
139  
140      expectedType = a.getExpectedType(); // Primitive types boolean and number omit difference below.
141      // For example, omit difference for expect.stringMatching(regexp)
142  
143      omitDifference = expectedType === 'string';
144    }
145  
146    if (expectedType !== (0, _jestGetType.default)(b)) {
147      return (
148        '  Comparing two different types of values.' +
149        ` Expected ${_chalk.default.green(expectedType)} but ` +
150        `received ${_chalk.default.red((0, _jestGetType.default)(b))}.`
151      );
152    }
153  
154    if (omitDifference) {
155      return null;
156    }
157  
158    switch (aType) {
159      case 'string':
160        return (0, _diffLines.diffLinesUnified)(
161          a.split('\n'),
162          b.split('\n'),
163          options
164        );
165  
166      case 'boolean':
167      case 'number':
168        return comparePrimitive(a, b, options);
169  
170      case 'map':
171        return compareObjects(sortMap(a), sortMap(b), options);
172  
173      case 'set':
174        return compareObjects(sortSet(a), sortSet(b), options);
175  
176      default:
177        return compareObjects(a, b, options);
178    }
179  }
180  
181  function comparePrimitive(a, b, options) {
182    const aFormat = (0, _prettyFormat.default)(a, FORMAT_OPTIONS);
183    const bFormat = (0, _prettyFormat.default)(b, FORMAT_OPTIONS);
184    return aFormat === bFormat
185      ? getCommonMessage(_constants.NO_DIFF_MESSAGE, options)
186      : (0, _diffLines.diffLinesUnified)(
187          aFormat.split('\n'),
188          bFormat.split('\n'),
189          options
190        );
191  }
192  
193  function sortMap(map) {
194    return new Map(Array.from(map.entries()).sort());
195  }
196  
197  function sortSet(set) {
198    return new Set(Array.from(set.values()).sort());
199  }
200  
201  function compareObjects(a, b, options) {
202    let difference;
203    let hasThrown = false;
204    const noDiffMessage = getCommonMessage(_constants.NO_DIFF_MESSAGE, options);
205  
206    try {
207      const aCompare = (0, _prettyFormat.default)(a, FORMAT_OPTIONS_0);
208      const bCompare = (0, _prettyFormat.default)(b, FORMAT_OPTIONS_0);
209  
210      if (aCompare === bCompare) {
211        difference = noDiffMessage;
212      } else {
213        const aDisplay = (0, _prettyFormat.default)(a, FORMAT_OPTIONS);
214        const bDisplay = (0, _prettyFormat.default)(b, FORMAT_OPTIONS);
215        difference = (0, _diffLines.diffLinesUnified2)(
216          aDisplay.split('\n'),
217          bDisplay.split('\n'),
218          aCompare.split('\n'),
219          bCompare.split('\n'),
220          options
221        );
222      }
223    } catch {
224      hasThrown = true;
225    } // If the comparison yields no results, compare again but this time
226    // without calling `toJSON`. It's also possible that toJSON might throw.
227  
228    if (difference === undefined || difference === noDiffMessage) {
229      const aCompare = (0, _prettyFormat.default)(a, FALLBACK_FORMAT_OPTIONS_0);
230      const bCompare = (0, _prettyFormat.default)(b, FALLBACK_FORMAT_OPTIONS_0);
231  
232      if (aCompare === bCompare) {
233        difference = noDiffMessage;
234      } else {
235        const aDisplay = (0, _prettyFormat.default)(a, FALLBACK_FORMAT_OPTIONS);
236        const bDisplay = (0, _prettyFormat.default)(b, FALLBACK_FORMAT_OPTIONS);
237        difference = (0, _diffLines.diffLinesUnified2)(
238          aDisplay.split('\n'),
239          bDisplay.split('\n'),
240          aCompare.split('\n'),
241          bCompare.split('\n'),
242          options
243        );
244      }
245  
246      if (difference !== noDiffMessage && !hasThrown) {
247        difference =
248          getCommonMessage(_constants.SIMILAR_MESSAGE, options) +
249          '\n\n' +
250          difference;
251      }
252    }
253  
254    return difference;
255  }
256  
257  var _default = diff;
258  exports.default = _default;