(a: any, b: any, options?: DiffOptions, memorize: Memorize = DEFAULT_MEMORIZE)
| 83 | * @returns {string | null} a string diff |
| 84 | */ |
| 85 | export function diff(a: any, b: any, options?: DiffOptions, memorize: Memorize = DEFAULT_MEMORIZE): string | undefined { |
| 86 | if (Object.is(a, b)) { |
| 87 | return '' |
| 88 | } |
| 89 | |
| 90 | const aType = getType(a) |
| 91 | let expectedType = aType |
| 92 | let omitDifference = false |
| 93 | if (aType === 'object' && typeof a.asymmetricMatch === 'function') { |
| 94 | if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) { |
| 95 | // Do not know expected type of user-defined asymmetric matcher. |
| 96 | return undefined |
| 97 | } |
| 98 | if (typeof a.getExpectedType !== 'function') { |
| 99 | // For example, expect.anything() matches either null or undefined |
| 100 | return undefined |
| 101 | } |
| 102 | expectedType = a.getExpectedType() |
| 103 | // Primitive types boolean and number omit difference below. |
| 104 | // For example, omit difference for expect.stringMatching(regexp) |
| 105 | omitDifference = expectedType === 'string' |
| 106 | } |
| 107 | |
| 108 | if (expectedType !== getType(b)) { |
| 109 | const { aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator } |
| 110 | = normalizeDiffOptions(options) |
| 111 | const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options) |
| 112 | let aDisplay = prettyFormat(a, formatOptions) |
| 113 | let bDisplay = prettyFormat(b, formatOptions) |
| 114 | // even if prettyFormat prints successfully big objects, |
| 115 | // large string can choke later on (concatenation? RPC?), |
| 116 | // so truncate it to a reasonable length here. |
| 117 | // (For example, playwright's ElementHandle can become about 200_000_000 length string) |
| 118 | const MAX_LENGTH = 100_000 |
| 119 | function truncate(s: string) { |
| 120 | return s.length <= MAX_LENGTH ? s : (`${s.slice(0, MAX_LENGTH)}...`) |
| 121 | } |
| 122 | aDisplay = memorize('expected', truncate(aDisplay)) |
| 123 | bDisplay = memorize('actual', truncate(bDisplay)) |
| 124 | const aDiff = `${aColor(`${aIndicator} ${aAnnotation}:`)}\n${aDisplay}` |
| 125 | const bDiff = `${bColor(`${bIndicator} ${bAnnotation}:`)}\n${bDisplay}` |
| 126 | return `${aDiff}\n\n${bDiff}` |
| 127 | } |
| 128 | |
| 129 | if (omitDifference) { |
| 130 | return undefined |
| 131 | } |
| 132 | |
| 133 | switch (aType) { |
| 134 | case 'string': |
| 135 | return diffLinesUnified(a.split('\n'), b.split('\n'), options) |
| 136 | case 'boolean': |
| 137 | case 'number': |
| 138 | return comparePrimitive(a, b, options, memorize) |
| 139 | case 'map': |
| 140 | return compareObjects(sortMap(a), sortMap(b), options, memorize) |
| 141 | case 'set': |
| 142 | return compareObjects(sortSet(a), sortSet(b), options, memorize) |
no test coverage detected