Skip to content

Commit

Permalink
jest-diff: Export as ECMAScript module (#8873)
Browse files Browse the repository at this point in the history
* jest-diff: Export Diff constructor as value instead of type

* Rewrite as ECMAScript-TypeScript module

* Delete or TypeScript in README

* Add .default to example of CommonJS default export in README

* Rename and add as BREAKING to CHANGELOG

* Rewrite re-export as explicit import and export statements

* Edit description in CHANGELOG.md
  • Loading branch information
pedrottimark committed Aug 26, 2019
1 parent e39b8dc commit fb7b132
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 65 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
- `[babel-plugin-jest-hoist]` Show codeframe on static hoisting issues ([#8865](https://github.com/facebook/jest/pull/8865))
- `[jest-config]` [**BREAKING**] Set default display name color based on runner ([#8689](https://github.com/facebook/jest/pull/8689))
- `[jest-diff]` Add options for colors and symbols ([#8841](https://github.com/facebook/jest/pull/8841))
- `[jest-diff]` [**BREAKING**] Export as ECMAScript module ([#8873](https://github.com/facebook/jest/pull/8873))
- `[jest-runner]` Warn if a worker had to be force exited ([#8206](https://github.com/facebook/jest/pull/8206))
- `[@jest/test-result]` Create method to create empty `TestResult` ([#8867](https://github.com/facebook/jest/pull/8867))
- `[jest-worker]` [**BREAKING**] Return a promise from `end()`, resolving with the information whether workers exited gracefully ([#8206](https://github.com/facebook/jest/pull/8206))
Expand Down
84 changes: 53 additions & 31 deletions packages/jest-diff/README.md
Expand Up @@ -26,8 +26,8 @@ Given values and optional options, `diffLinesUnified(a, b, options?)` does the f

To use this function, write either of the following:

- `const diffLinesUnified = require('jest-diff');` in a CommonJS module
- `import diffLinesUnified from 'jest-diff';` in an ECMAScript module
- `const diffLinesUnified = require('jest-diff').default;` in CommonJS modules
- `import diffLinesUnified from 'jest-diff';` in ECMAScript modules

### Example of default export

Expand All @@ -40,8 +40,7 @@ const difference = diffLinesUnified(a, b);

The returned **string** consists of:

- annotation lines which describe the change symbols with labels
- blank line
- annotation lines: describe the two change symbols with labels, and a blank line
- comparison lines: similar to “unified” view on GitHub, but `Expected` lines are green, `Received` lines are red, and common lines are dim (by default, see Options)

```diff
Expand Down Expand Up @@ -77,8 +76,8 @@ Although the function is mainly for **multiline** strings, it compares any strin

Write either of the following:

- `const {diffStringsUnified} = require('jest-diff');` in a CommonJS module
- `import {diffStringsUnified} from 'jest-diff';` in an ECMAScript module
- `const {diffStringsUnified} = require('jest-diff');` in CommonJS modules
- `import {diffStringsUnified} from 'jest-diff';` in ECMAScript modules

### Example of diffStringsUnified

Expand All @@ -91,9 +90,8 @@ const difference = diffStringsUnified(a, b);

The returned **string** consists of:

- annotation lines which describe the change symbols with labels
- blank line
- comparison lines: similar to “unified” view on GitHub, and **changed substrings** have **inverted** foreground and background colors
- annotation lines: describe the two change symbols with labels, and a blank line
- comparison lines: similar to “unified” view on GitHub, and **changed substrings** have **inverted** foreground and background colors (which the following example does not show)

```diff
- Expected
Expand Down Expand Up @@ -121,62 +119,86 @@ If the input strings can have **arbitrary length**, we recommend that the callin

## Usage of diffStringsRaw

Given strings, `diffStringsRaw(a, b, cleanup)` does the following:
Given strings and boolean, `diffStringsRaw(a, b, cleanup)` does the following:

- **compare** the strings character-by-character using the `diff-sequences` package
- optionally **clean up** small (often coincidental) common substrings, also known as chaff

Write one of the following:

- `const {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diffStringsRaw} = require('jest-diff');` in a CommonJS module
- `import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diffStringsRaw} from 'jest-diff';` in an ECMAScript module
- `import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} from 'jest-diff';` in a TypeScript module
- `const {diffStringsRaw} = require('jest-diff');` in CommonJS modules
- `import {diffStringsRaw} from 'jest-diff';` in ECMAScript modules

The returned **array** describes substrings as instances of the `Diff` class (which calling code can access like array tuples).
Because `diffStringsRaw` returns the difference as **data** instead of a string, you can format it as your application requires (for example, enclosed in HTML markup for browser instead of escape sequences for console).

The returned **array** describes substrings as instances of the `Diff` class, which calling code can access like array tuples:

The value at index `0` is one of the following:

| value | named export | description |
| ----: | :------------ | :-------------------- |
| `0` | `DIFF_EQUAL` | in `a` and in `b` |
| `-1` | `DIFF_DELETE` | in `a` but not in `b` |
| `1` | `DIFF_INSERT` | in `b` but not in `a` |

Because `diffStringsRaw` returns the difference as **data** instead of a string, you are free to format it as your application requires (for example, enclosed in HTML markup for browser instead of escape sequences for console).
The value at index `1` is a substring of `a` or `b` or both.

### Example of diffStringsRaw with cleanup

```js
const diffs = diffStringsRaw('change from', 'change to', true);

// diffs[0][0] === DIFF_EQUAL
// diffs[0][1] === 'change '
/*
diffs[0][0] === 0 // DIFF_EQUAL
diffs[0][1] === 'change '
// diffs[1][0] === DIFF_DELETE
// diffs[1][1] === 'from'
diffs[1][0] === -1 // DIFF_DELETE
diffs[1][1] === 'from'
// diffs[2][0] === DIFF_INSERT
// diffs[2][1] === 'to'
diffs[2][0] === 1 // DIFF_INSERT
diffs[2][1] === 'to'
*/
```

### Example of diffStringsRaw without cleanup

```js
const diffs = diffStringsRaw('change from', 'change to', false);

// diffs[0][0] === DIFF_EQUAL
// diffs[0][1] === 'change '
/*
diffs[0][0] === 0 // DIFF_EQUAL
diffs[0][1] === 'change '
// diffs[1][0] === DIFF_DELETE
// diffs[1][1] === 'fr'
diffs[1][0] === -1 // DIFF_DELETE
diffs[1][1] === 'fr'
// diffs[2][0] === DIFF_INSERT
// diffs[2][1] === 't'
diffs[2][0] === 1 // DIFF_INSERT
diffs[2][1] === 't'
// Here is a small coincidental common substring:
// diffs[3][0] === DIFF_EQUAL
// diffs[3][1] === 'o'
diffs[3][0] === 0 // DIFF_EQUAL
diffs[3][1] === 'o'
diffs[4][0] === -1 // DIFF_DELETE
diffs[4][1] === 'm'
*/
```

## Advanced import for diffStringsRaw

// diffs[4][0] === DIFF_DELETE
// diffs[4][1] === 'm'
Here are all the named imports for the `diffStringsRaw` function:

- `const {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} = require('jest-diff');` in CommonJS modules
- `import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} from 'jest-diff';` in ECMAScript modules

To write a **formatting** function, you might need the named constants (and `Diff` in TypeScript annotations).

If you write an application-specific **cleanup** algorithm, then you might need to call the `Diff` constructor:

```js
const diffCommon = new Diff(DIFF_EQUAL, 'change ');
const diffDelete = new Diff(DIFF_DELETE, 'from');
const diffInsert = new Diff(DIFF_INSERT, 'to');
```

## Options
Expand Down
34 changes: 34 additions & 0 deletions packages/jest-diff/src/__tests__/diffStringsRaw.test.ts
@@ -0,0 +1,34 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} from '../';

describe('diffStringsRaw', () => {
test('one-line with cleanup', () => {
const expected: Array<Diff> = [
new Diff(DIFF_EQUAL, 'change '),
new Diff(DIFF_DELETE, 'from'),
new Diff(DIFF_INSERT, 'to'),
];
const received = diffStringsRaw('change from', 'change to', true);

expect(received).toEqual(expected);
});

test('one-line without cleanup', () => {
const expected: Array<Diff> = [
new Diff(DIFF_EQUAL, 'change '),
new Diff(DIFF_DELETE, 'fr'),
new Diff(DIFF_INSERT, 't'),
new Diff(DIFF_EQUAL, 'o'),
new Diff(DIFF_DELETE, 'm'),
];
const received = diffStringsRaw('change from', 'change to', false);

expect(received).toEqual(expected);
});
});
30 changes: 9 additions & 21 deletions packages/jest-diff/src/index.ts
Expand Up @@ -8,17 +8,17 @@
import prettyFormat = require('pretty-format');
import chalk from 'chalk';
import getType = require('jest-get-type');
import {
DIFF_DELETE,
DIFF_EQUAL,
DIFF_INSERT,
Diff as DiffClass,
} from './cleanupSemantic';
import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff} from './cleanupSemantic';
import diffLines from './diffLines';
import {normalizeDiffOptions} from './normalizeDiffOptions';
import {diffStringsRaw, diffStringsUnified} from './printDiffs';
import {NO_DIFF_MESSAGE, SIMILAR_MESSAGE} from './constants';
import {DiffOptionsNormalized, DiffOptions as JestDiffOptions} from './types';
import {DiffOptionsNormalized, DiffOptions as ImportDiffOptions} from './types';

export type DiffOptions = ImportDiffOptions;

export {diffStringsRaw, diffStringsUnified};
export {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff};

const {
AsymmetricMatcher,
Expand Down Expand Up @@ -50,7 +50,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?: JestDiffOptions): string | null {
function diff(a: any, b: any, options?: DiffOptions): string | null {
if (Object.is(a, b)) {
return NO_DIFF_MESSAGE;
}
Expand Down Expand Up @@ -163,16 +163,4 @@ function compareObjects(
return diffMessage;
}

// eslint-disable-next-line no-redeclare
namespace diff {
export type Diff = DiffClass;
export type DiffOptions = JestDiffOptions;
}

diff.diffStringsUnified = diffStringsUnified;
diff.diffStringsRaw = diffStringsRaw;
diff.DIFF_DELETE = DIFF_DELETE;
diff.DIFF_EQUAL = DIFF_EQUAL;
diff.DIFF_INSERT = DIFF_INSERT;

export = diff;
export default diff;
22 changes: 11 additions & 11 deletions packages/jest-matcher-utils/src/index.ts
Expand Up @@ -6,17 +6,17 @@
*/

import chalk from 'chalk';
import jestDiff = require('jest-diff');
import getType = require('jest-get-type');
import prettyFormat = require('pretty-format');

const {
import diffLinesUnified, {
DIFF_DELETE,
DIFF_EQUAL,
DIFF_INSERT,
Diff,
DiffOptions as ImportDiffOptions,
diffStringsRaw,
diffStringsUnified,
} = jestDiff;
} from 'jest-diff';
import getType = require('jest-get-type');
import prettyFormat = require('pretty-format');

const {
AsymmetricMatcher,
Expand Down Expand Up @@ -49,7 +49,7 @@ export type MatcherHintOptions = {
secondArgumentColor?: MatcherHintColor;
};

export type DiffOptions = jestDiff.DiffOptions;
export type DiffOptions = ImportDiffOptions;

export const EXPECTED_COLOR = chalk.green;
export const RECEIVED_COLOR = chalk.red;
Expand Down Expand Up @@ -226,12 +226,12 @@ export const ensureExpectedIsNonNegativeInteger = (
// * include change substrings which have argument op
// with inverse highlight only if there is a common substring
const getCommonAndChangedSubstrings = (
diffs: Array<jestDiff.Diff>,
diffs: Array<Diff>,
op: number,
hasCommonDiff: boolean,
): string =>
diffs.reduce(
(reduced: string, diff: jestDiff.Diff): string =>
(reduced: string, diff: Diff): string =>
reduced +
(diff[0] === DIFF_EQUAL
? diff[1]
Expand Down Expand Up @@ -338,7 +338,7 @@ export const printDiffOrStringify = (
}

if (isLineDiffable(expected, received)) {
const difference = jestDiff(expected, received, {
const difference = diffLinesUnified(expected, received, {
aAnnotation: expectedLabel,
bAnnotation: receivedLabel,
expand,
Expand Down Expand Up @@ -378,7 +378,7 @@ const shouldPrintDiff = (actual: unknown, expected: unknown) => {
};

export const diff = (a: any, b: any, options?: DiffOptions): string | null =>
shouldPrintDiff(a, b) ? jestDiff(a, b, options) : null;
shouldPrintDiff(a, b) ? diffLinesUnified(a, b, options) : null;

export const pluralize = (word: string, count: number) =>
(NUMBERS[count] || count) + ' ' + word + (count === 1 ? '' : 's');
Expand Down
4 changes: 2 additions & 2 deletions packages/jest-snapshot/src/print.ts
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import diff = require('jest-diff');
import diff, {diffStringsUnified} from 'jest-diff';
import getType = require('jest-get-type');
import {
EXPECTED_COLOR,
Expand Down Expand Up @@ -86,7 +86,7 @@ export const printDiffOrStringified = (
receivedSerializedTrimmed.length <= MAX_DIFF_STRING_LENGTH &&
expectedSerializedTrimmed !== receivedSerializedTrimmed
) {
return diff.diffStringsUnified(
return diffStringsUnified(
expectedSerializedTrimmed,
receivedSerializedTrimmed,
{
Expand Down

0 comments on commit fb7b132

Please sign in to comment.