-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
jest-diff: Add options for colors and symbols #8841
Merged
Merged
Changes from 6 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d375c26
jest-diff: Add options for colors and symbols
pedrottimark 707fa69
Fix prettier lint errors in README
pedrottimark 664f191
Delete unneeded prettier-ignore comment from README
pedrottimark c23118b
Edit name of function in comment
pedrottimark 0246ae0
Update CHANGELOG.md
pedrottimark ddee70f
Add copyright and license comment to added source file
pedrottimark d03a394
Update packages/jest-diff/README.md
pedrottimark e4b2ba0
Resolve merge conflict related to sort-imports rule
pedrottimark bf23383
Fix lint error sort-imports
pedrottimark 9a4a7f7
Rename diffStringsAligned as diffStringsUnified
pedrottimark 43b2d4c
Remove diffStringsUnaligned call from jest-snapshot
pedrottimark 7829d51
Replace diffStringsUnaligned with diffStringsRaw
pedrottimark 67b2127
Add omitAnnotationLines option
pedrottimark 97d13bd
Example of option to omit annotation lines
pedrottimark 81ba9ee
Resolve merge conflicts
pedrottimark a2ad226
Correct reference to exported Diff type
pedrottimark 61b18f7
Add sentence about diffStringsRaw to jest-diff README
pedrottimark 109d706
Refactor to call diffStringsRaw from diffStringsUnified
pedrottimark 27b3313
Resolve merge conflict in CHANGELOG.md
pedrottimark File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
# 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: | ||
|
||
- `diffStringsAligned` returns a string which includes comparison lines. | ||
- `diffStringsUnaligned` returns an array of 2 strings. | ||
|
||
## 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, `diffLines(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 `diffLines` as the function name, write either of the following: | ||
pedrottimark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- `const diffLines = require('jest-diff');` in a CommonJS module | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we'll probably go for named exports in jest 25 (we wanna avoid having to use |
||
- `import diffLines from 'jest-diff';` in an ECMAScript module | ||
|
||
### Example of default export | ||
|
||
```js | ||
const a = ['delete', 'change from', 'common']; | ||
const b = ['change to', 'insert', 'common']; | ||
|
||
const difference = diffLines(a, b); | ||
``` | ||
|
||
The returned **string** consists of: | ||
|
||
- annotation lines which describe the change symbols with labels | ||
- blank line | ||
- comparison lines in which `Expected` lines are green, `Received` lines are red, and common lines are dim | ||
|
||
```diff | ||
- Expected | ||
SimenB marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ 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 diffStringsAligned | ||
|
||
Given strings and optional options, `diffStringsAligned(a, b, options?)` does the following: | ||
|
||
- **compare** the strings character-by-character using the `diff-sequences` package | ||
- **clean up** small (often coincidental) common substrings, 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 {diffStringsAligned} = require('jest-diff');` in a CommonJS module | ||
- `import {diffStringsAligned} from 'jest-diff';` in an ECMAScript module | ||
|
||
### Example of diffStringsAligned | ||
|
||
```js | ||
const a = 'change from\ncommon'; | ||
const b = 'change to\ncommon'; | ||
|
||
const difference = diffStringsAligned(a, b); | ||
``` | ||
|
||
The returned **string** consists of: | ||
|
||
- annotation lines which describe the change symbols with labels | ||
- blank line | ||
- comparison lines in which **changed substrings** have **inverted** foreground and background colors (for example, `from` is white-on-green and `to` is white-on-red) | ||
|
||
```diff | ||
- Expected | ||
+ Received | ||
|
||
- change from | ||
+ change to | ||
common | ||
``` | ||
|
||
### Edge cases of diffStringsAligned | ||
|
||
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 diffStringsAligned | ||
|
||
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 diffStringsUnaligned | ||
|
||
Given strings, `diffStringsUnaligned(a, b)` does the following: | ||
|
||
- **compare** the strings character-by-character using the `diff-sequences` package | ||
- **clean up** small (often coincidental) common substrings, known as “chaff” | ||
- **format** the changed substrings using `inverse` from the `chalk` package | ||
|
||
Although the function is mainly for **one-line** strings, it compares any strings. | ||
|
||
Write either of the following: | ||
|
||
- `const {diffStringsUnaligned} = require('jest-diff');` in a CommonJS module | ||
- `import {diffStringsUnaligned} from 'jest-diff';` in an ECMAScript module | ||
|
||
### Example of diffStringsUnaligned | ||
|
||
```js | ||
const [a, b] = diffStringsUnaligned('change from', 'change to'); | ||
|
||
// a === 'change ' + chalk.inverse('from') | ||
// b === 'change ' + chalk.inverse('to') | ||
``` | ||
|
||
The returned **array** of **two strings** corresponds to the two arguments. | ||
|
||
Because the caller is responsible to format the returned strings, there are no options. | ||
|
||
## 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: | ||
|
||
- `diffLines(a, b, options)` | ||
- `diffStringsAligned(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` | | ||
|
||
### Example of options for labels | ||
|
||
If the application is code modification, you might replace the labels: | ||
|
||
```js | ||
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: | ||
|
||
```js | ||
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: | ||
|
||
```js | ||
const options = { | ||
commonColor: line => line, | ||
}; | ||
``` | ||
|
||
### Example of options for symbols | ||
|
||
For consistency with the `diff` command, you might replace the symbols: | ||
|
||
```js | ||
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: | ||
|
||
```js | ||
const options = { | ||
contextLines: 1, | ||
expand: false, | ||
}; | ||
``` | ||
|
||
A patch mark like `@@ -12,7 +12,9 @@` accounts for omitted common lines. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took me quite a while (even after reading the whole readme) to understand the difference between those two. I still do not quite understand the naming, which I think was part of what confused me because I associated things like the beginning of lines with "aligned".
Would you say that unified diff vs split diff (like for example in GitHub) is a good analogy for those functions and could be used for naming?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed on being a bit confused about what
aligned
means. Unified vs split makes more sense to me (that's also the naming bitbucket uses, so I think it's pretty standard)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brilliant analogy!
For multiline strings, a split like GitHub would consist of array of string tuples:
for corresponding changed chunks. For deleted
b
is empty, for inserteda
is empty.I am curious, can y’all think of a use case in third-party dependents?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diffStringsAligned
anddiffStringsUnified
diffStringsUnaligned
withdiffStringsRaw
that returns an array ofDiff
objects, so that it will be reusable to the max