Skip to content

Latest commit

 

History

History
291 lines (198 loc) · 8.56 KB

README.md

File metadata and controls

291 lines (198 loc) · 8.56 KB

jest-diff

Display differences clearly so people can review changes confidently.

The default export serializes JavaScript values and compares them line-by-line.

Two named exports compare strings character-by-character:

  • diffStringsUnified returns a string which includes comparison lines.
  • diffStringsRaw returns an array of Diff objects.

Installation

To add this package as a dependency of a project, run either of the following commands:

  • npm install jest-diff
  • yarn add jest-diff

Usage of default export

Given values and optional options, diffLinesUnified(a, b, options?) does the following:

  • serialize the values as strings using the pretty-format package
  • compare the strings line-by-line using the diff-sequences package
  • format the changed or common lines using the chalk package

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

Example of default export

const a = ['delete', 'change from', 'common'];
const b = ['change to', 'insert', 'common'];

const difference = diffLinesUnified(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, but Expected lines are green, Received lines are red, and common lines are dim (by default, see Options)
- Expected
+ Received

  Array [
-   "delete",
-   "change from",
+   "change to",
+   "insert",
    "common",
  ]

Edge cases of default export

Here are edge cases for the return value:

  • ' Comparing two different types of values. …' if the arguments have different types according to the jest-get-type package (instances of different classes have the same 'object' type)
  • 'Compared values have no visual difference.' if the arguments have either referential identity according to Object.is method or same serialization according to the pretty-format package
  • null if either argument is a so-called asymmetric matcher in Jasmine or Jest

Usage of diffStringsUnified

Given strings and optional options, diffStringsUnified(a, b, options?) does the following:

  • compare the strings character-by-character using the diff-sequences package
  • clean up small (often coincidental) common substrings, also known as chaff
  • format the changed or common lines using the chalk package

Although the function is mainly for multiline strings, it compares any strings.

Write either of the following:

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

Example of diffStringsUnified

const a = 'change from\ncommon';
const b = 'change to\ncommon';

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
- Expected
+ Received

- change from
+ change to
  common

Edge cases of diffStringsUnified

Here are edge cases for the return value:

  • both a and b are empty strings: no comparison lines
  • only a is empty string: all comparison lines have bColor and bSymbol (see Options)
  • only b is empty string: all comparison lines have aColor and aSymbol (see Options)
  • a and b are equal non-empty strings: all comparison lines have commonColor and commonSymbol (see Options)

Performance of diffStringsUnified

To get the benefit of changed substrings within the comparison lines, a character-by-character comparison has a higher computational cost (in time and space) than a line-by-line comparison.

If the input strings can have arbitrary length, we recommend that the calling code set a limit, beyond which it calls the default export instead. For example, Jest falls back to line-by-line comparison if either string has length greater than 20K characters.

Usage of diffStringsRaw

Given strings, 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

The returned array describes substrings as instances of the Diff class (which calling code can access like array tuples).

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).

Example of diffStringsRaw with cleanup

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

// diffs[0][0] === DIFF_EQUAL
// diffs[0][1] === 'change '

// diffs[1][0] === DIFF_DELETE
// diffs[1][1] === 'from'

// diffs[2][0] === DIFF_INSERT
// diffs[2][1] === 'to'

Example of diffStringsRaw without cleanup

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

// diffs[0][0] === DIFF_EQUAL
// diffs[0][1] === 'change '

// diffs[1][0] === DIFF_DELETE
// diffs[1][1] === 'fr'

// diffs[2][0] === DIFF_INSERT
// diffs[2][1] === 't'

// Here is a small coincidental common substring:
// diffs[3][0] === DIFF_EQUAL
// diffs[3][1] === 'o'

// diffs[4][0] === DIFF_DELETE
// diffs[4][1] === 'm'

Options

The default options are for the report when an assertion fails from the expect package used by Jest.

For other applications, you can provide an options object as a third argument:

  • diffLinesUnified(a, b, options)
  • diffStringsUnified(a, b, options)

Properties of options object

name default
aAnnotation 'Expected'
aColor chalk.green
aSymbol '-'
bAnnotation 'Received'
bColor chalk.red
bSymbol '+'
commonColor chalk.dim
commonSymbol ' '
contextLines 5
expand true
omitAnnotationLines false

Example of options for labels

If the application is code modification, you might replace the labels:

const options = {
  aAnnotation: 'Original',
  bAnnotation: 'Modified',
};

The jest-diff package does not assume that the 2 labels have equal length.

Example of options for colors

For consistency with most diff tools, you might exchange the colors:

import chalk from 'chalk';

const options = {
  aColor: chalk.red,
  bColor: chalk.green,
};

Example of option to keep the default color

The value of a color option is a function, which given a string, returns a string.

For common lines to keep the default (usually black) color, you might provide an identity function:

const options = {
  commonColor: line => line,
};

Example of options for symbols

For consistency with the diff command, you might replace the symbols:

const options = {
  aSymbol: '<',
  bSymbol: '>',
};

The jest-diff package assumes (but does not enforce) that the 3 symbols have equal length.

Example of options to limit common lines

By default, the output includes all common lines.

To emphasize the changes, you might limit the number of common “context” lines:

const options = {
  contextLines: 1,
  expand: false,
};

A patch mark like @@ -12,7 +12,9 @@ accounts for omitted common lines.

Example of option to omit annotation lines

To display only the comparison lines:

const a = 'change from\ncommon';
const b = 'change to\ncommon';
const options = {
  omitAnnotationLines: true,
};

const difference = diffStringsUnified(a, b, options);
- change from
+ change to
  common