diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c60e81dd02b..2937be0fe079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - `[jest-runtime]` Add `jest.isolateModules` for scoped module initialization ([#6701](https://github.com/facebook/jest/pull/6701)) +- `[jest-diff]` [**BREAKING**] Support diffing numbers and booleans instead of returning null for different ones ([#7605](https://github.com/facebook/jest/pull/7605)) - `[jest-diff]` [**BREAKING**] Replace `diff` with `diff-sequences` package ([#6961](https://github.com/facebook/jest/pull/6961)) - `[jest-cli]` [**BREAKING**] Only set error process error codes when they are non-zero ([#7363](https://github.com/facebook/jest/pull/7363)) - `[jest-config]` [**BREAKING**] Deprecate `setupTestFrameworkScriptFile` in favor of new `setupFilesAfterEnv` ([#7119](https://github.com/facebook/jest/pull/7119)) @@ -54,6 +55,7 @@ ### Fixes +- `[jest-diff]` Do not claim that `-0` and `0` have no visual difference ([#7605](https://github.com/facebook/jest/pull/7605)) - `[jest-mock]` Fix automock for numeric function names ([#7653](https://github.com/facebook/jest/pull/7653)) - `[jest-config]` Ensure `existsSync` is only called with a string parameter ([#7607](https://github.com/facebook/jest/pull/7607)) - `[expect]` `toStrictEqual` considers sparseness of arrays. ([#7591](https://github.com/facebook/jest/pull/7591)) diff --git a/e2e/__tests__/__snapshots__/failures.test.js.snap b/e2e/__tests__/__snapshots__/failures.test.js.snap index 41ff2da7a002..d6cdac0e6940 100644 --- a/e2e/__tests__/__snapshots__/failures.test.js.snap +++ b/e2e/__tests__/__snapshots__/failures.test.js.snap @@ -540,10 +540,6 @@ FAIL __tests__/assertionError.test.js Received: 1 - Difference: - - Compared values have no visual difference. - 33 | 34 | test('assert.notEqual', () => { > 35 | assert.notEqual(1, 1); @@ -677,10 +673,6 @@ FAIL __tests__/assertionError.test.js Message: My custom error message - Difference: - - Compared values have no visual difference. - 53 | 54 | test('assert.notStrictEqual', () => { > 55 | assert.notStrictEqual(1, 1, 'My custom error message'); diff --git a/packages/expect/package.json b/packages/expect/package.json index 0a6b1c3c28c3..f357e11b07a6 100644 --- a/packages/expect/package.json +++ b/packages/expect/package.json @@ -11,7 +11,6 @@ "browser": "build-es5/index.js", "dependencies": { "ansi-styles": "^3.2.0", - "jest-diff": "^23.6.0", "jest-get-type": "^22.1.0", "jest-matcher-utils": "^23.6.0", "jest-message-util": "^23.4.0", diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index f8e39e5fc99a..1debb403a675 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -360,11 +360,7 @@ exports[`.toBe() fails for: -0 and 0 1`] = ` "expect(received).toBe(expected) // Object.is equality Expected: 0 -Received: -0 - -Difference: - -Compared values have no visual difference." +Received: -0" `; exports[`.toBe() fails for: 1 and 2 1`] = ` diff --git a/packages/expect/src/matchers.js b/packages/expect/src/matchers.js index 345f40341f87..298f1d1cb681 100644 --- a/packages/expect/src/matchers.js +++ b/packages/expect/src/matchers.js @@ -9,7 +9,6 @@ import type {MatchersObject} from 'types/Matchers'; -import diff from 'jest-diff'; import getType from 'jest-get-type'; import {escapeStrForRegex} from 'jest-regex-util'; import { @@ -17,6 +16,7 @@ import { RECEIVED_COLOR, SUGGEST_TO_EQUAL, SUGGEST_TO_CONTAIN_EQUAL, + diff, ensureNoExpected, ensureNumbers, getLabelPrinter, diff --git a/packages/expect/src/spyMatchers.js b/packages/expect/src/spyMatchers.js index 0d7016a2d37b..50f623d9c770 100644 --- a/packages/expect/src/spyMatchers.js +++ b/packages/expect/src/spyMatchers.js @@ -13,6 +13,7 @@ const CALL_PRINT_LIMIT = 3; const RETURN_PRINT_LIMIT = 5; const LAST_CALL_PRINT_LIMIT = 1; import { + diff, ensureExpectedIsNumber, ensureNoExpected, EXPECTED_COLOR, @@ -26,7 +27,6 @@ import { } from 'jest-matcher-utils'; import {equals} from './jasmineUtils'; import {iterableEquality, partition, isOneline} from './utils'; -import diff from 'jest-diff'; const createToBeCalledMatcher = matcherName => (received, expected) => { ensureNoExpected(expected, matcherName); diff --git a/packages/jest-circus/package.json b/packages/jest-circus/package.json index 7778c15cdd52..f3b4ede5d59f 100644 --- a/packages/jest-circus/package.json +++ b/packages/jest-circus/package.json @@ -14,7 +14,6 @@ "co": "^4.6.0", "expect": "^23.6.0", "is-generator-fn": "^2.0.0", - "jest-diff": "^23.6.0", "jest-each": "^23.6.0", "jest-matcher-utils": "^23.6.0", "jest-message-util": "^23.4.0", @@ -25,6 +24,7 @@ }, "devDependencies": { "execa": "^1.0.0", + "jest-diff": "^23.6.0", "jest-runtime": "^23.6.0" }, "engines": { diff --git a/packages/jest-circus/src/formatNodeAssertErrors.js b/packages/jest-circus/src/formatNodeAssertErrors.js index 792ef5ad0641..a13caf678687 100644 --- a/packages/jest-circus/src/formatNodeAssertErrors.js +++ b/packages/jest-circus/src/formatNodeAssertErrors.js @@ -10,9 +10,8 @@ import type {DiffOptions} from 'jest-diff/src/diffStrings'; import type {Event, State} from 'types/Circus'; -import {printExpected, printReceived} from 'jest-matcher-utils'; +import {diff, printExpected, printReceived} from 'jest-matcher-utils'; import chalk from 'chalk'; -import diff from 'jest-diff'; import prettyFormat from 'pretty-format'; type AssertionError = {| diff --git a/packages/jest-diff/src/__tests__/diff.test.js b/packages/jest-diff/src/__tests__/diff.test.js index 58a622b89c18..50df67c274f7 100644 --- a/packages/jest-diff/src/__tests__/diff.test.js +++ b/packages/jest-diff/src/__tests__/diff.test.js @@ -48,9 +48,12 @@ describe('no visual difference', () => { [[], []], [[1, 2], [1, 2]], [11, 11], + [NaN, NaN], + [Number.NaN, NaN], [() => {}, () => {}], [null, null], [undefined, undefined], + [false, false], [{a: 1}, {a: 1}], [{a: {b: 5}}, {a: {b: 5}}], ].forEach(values => { @@ -178,13 +181,17 @@ describe('objects', () => { }); test('numbers', () => { - const result = diff(123, 234); - expect(result).toBe(null); + expect(stripped(1, 2)).toEqual(expect.stringContaining('- 1\n+ 2')); +}); + +test('-0 and 0', () => { + expect(stripped(-0, 0)).toEqual(expect.stringContaining('- -0\n+ 0')); }); test('booleans', () => { - const result = diff(true, false); - expect(result).toBe(null); + expect(stripped(false, true)).toEqual( + expect.stringContaining('- false\n+ true'), + ); }); describe('multiline string non-snapshot', () => { diff --git a/packages/jest-diff/src/index.js b/packages/jest-diff/src/index.js index 716e863fb1c4..a52fa1c1b524 100644 --- a/packages/jest-diff/src/index.js +++ b/packages/jest-diff/src/index.js @@ -46,7 +46,7 @@ const FALLBACK_FORMAT_OPTIONS_0 = {...FALLBACK_FORMAT_OPTIONS, indent: 0}; // Generate a string that will highlight the difference between two values // with green and red. (similar to how github does code diffing) function diff(a: any, b: any, options: ?DiffOptions): ?string { - if (a === b) { + if (Object.is(a, b)) { return NO_DIFF_MESSAGE; } @@ -83,9 +83,9 @@ function diff(a: any, b: any, options: ?DiffOptions): ?string { switch (aType) { case 'string': return diffStrings(a, b, options); - case 'number': case 'boolean': - return null; + case 'number': + return comparePrimitive(a, b, options); case 'map': return compareObjects(sortMap(a), sortMap(b), options); case 'set': @@ -95,6 +95,18 @@ function diff(a: any, b: any, options: ?DiffOptions): ?string { } } +function comparePrimitive( + a: number | boolean, + b: number | boolean, + options: ?DiffOptions, +) { + return diffStrings( + prettyFormat(a, FORMAT_OPTIONS), + prettyFormat(b, FORMAT_OPTIONS), + options, + ); +} + function sortMap(map) { return new Map(Array.from(map.entries()).sort()); } diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 454a2e9e0d3f..e67ff83d48b4 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -14,7 +14,6 @@ "co": "^4.6.0", "expect": "^23.6.0", "is-generator-fn": "^2.0.0", - "jest-diff": "^23.6.0", "jest-each": "^23.6.0", "jest-matcher-utils": "^23.6.0", "jest-message-util": "^23.4.0", @@ -23,6 +22,7 @@ "pretty-format": "^23.6.0" }, "devDependencies": { + "jest-diff": "^23.6.0", "jest-runtime": "^23.6.0" }, "engines": { diff --git a/packages/jest-jasmine2/src/assertionErrorMessage.js b/packages/jest-jasmine2/src/assertionErrorMessage.js index 5051c8d1c250..3e066ae8377d 100644 --- a/packages/jest-jasmine2/src/assertionErrorMessage.js +++ b/packages/jest-jasmine2/src/assertionErrorMessage.js @@ -9,9 +9,8 @@ import type {DiffOptions} from 'jest-diff/src/diffStrings'; -import {printReceived, printExpected} from 'jest-matcher-utils'; +import {diff, printReceived, printExpected} from 'jest-matcher-utils'; import chalk from 'chalk'; -import diff from 'jest-diff'; type AssertionError = {| actual: ?string, diff --git a/packages/jest-matcher-utils/package.json b/packages/jest-matcher-utils/package.json index 15f3019ef755..beaeacc8b9dc 100644 --- a/packages/jest-matcher-utils/package.json +++ b/packages/jest-matcher-utils/package.json @@ -14,6 +14,7 @@ "main": "build/index.js", "dependencies": { "chalk": "^2.0.1", + "jest-diff": "^23.6.0", "jest-get-type": "^22.1.0", "pretty-format": "^23.6.0" } diff --git a/packages/jest-matcher-utils/src/__tests__/index.test.js b/packages/jest-matcher-utils/src/__tests__/index.test.js index 229e8f5b8a72..703ab50fa0d0 100644 --- a/packages/jest-matcher-utils/src/__tests__/index.test.js +++ b/packages/jest-matcher-utils/src/__tests__/index.test.js @@ -7,6 +7,7 @@ */ import { + diff, ensureNumbers, ensureNoExpected, getLabelPrinter, @@ -129,6 +130,31 @@ describe('.ensureNoExpected()', () => { }); }); +jest.mock('jest-diff', () => () => 'diff output'); +describe('diff', () => { + test('forwards to jest-diff', () => { + [ + ['a', 'b'], + ['a', {}], + ['a', null], + ['a', undefined], + ['a', 1], + ['a', true], + [1, true], + ].forEach(([actual, expected]) => + expect(diff(actual, expected)).toBe('diff output'), + ); + }); + + test('two booleans', () => { + expect(diff(false, true)).toBe(null); + }); + + test('two numbers', () => { + expect(diff(1, 2)).toBe(null); + }); +}); + describe('.pluralize()', () => { test('one', () => expect(pluralize('apple', 1)).toEqual('one apple')); test('two', () => expect(pluralize('apple', 2)).toEqual('two apples')); diff --git a/packages/jest-matcher-utils/src/index.js b/packages/jest-matcher-utils/src/index.js index f969e9363b9b..a7b040e867a5 100644 --- a/packages/jest-matcher-utils/src/index.js +++ b/packages/jest-matcher-utils/src/index.js @@ -10,6 +10,7 @@ import type {MatcherHintOptions} from 'types/Matchers'; import chalk from 'chalk'; +import jestDiff from 'jest-diff'; import getType from 'jest-get-type'; import prettyFormat from 'pretty-format'; const { @@ -160,6 +161,21 @@ export const ensureNumbers = ( ensureExpectedIsNumber(expected, matcherName); }; +// Sometimes, e.g. when comparing two numbers, the output from jest-diff +// does not contain more information than the `Expected:` / `Received:` already gives. +// In those cases, we do not print a diff to make the output shorter and not redundant. +const shouldPrintDiff = (actual: any, expected: any) => { + if (typeof actual === 'number' && typeof expected === 'number') { + return false; + } + if (typeof actual === 'boolean' && typeof expected === 'boolean') { + return false; + } + return true; +}; +export const diff: typeof jestDiff = (a, b, options) => + shouldPrintDiff(a, b) ? jestDiff(a, b, options) : null; + export const pluralize = (word: string, count: number) => (NUMBERS[count] || count) + ' ' + word + (count === 1 ? '' : 's');