UNPKG

13 kBMarkdownView Raw
1# pretty-format
2
3Stringify any JavaScript value.
4
5- Serialize built-in JavaScript types.
6- Serialize application-specific data types with built-in or user-defined plugins.
7
8## Installation
9
10```sh
11$ yarn add pretty-format
12```
13
14## Usage
15
16```js
17const {format: prettyFormat} = require('pretty-format'); // CommonJS
18```
19
20```js
21import {format as prettyFormat} from 'pretty-format'; // ES2015 modules
22```
23
24```js
25const val = {object: {}};
26val.circularReference = val;
27val[Symbol('foo')] = 'foo';
28val.map = new Map([['prop', 'value']]);
29val.array = [-0, Infinity, NaN];
30
31console.log(prettyFormat(val));
32/*
33Object {
34 "array": Array [
35 -0,
36 Infinity,
37 NaN,
38 ],
39 "circularReference": [Circular],
40 "map": Map {
41 "prop" => "value",
42 },
43 "object": Object {},
44 Symbol(foo): "foo",
45}
46*/
47```
48
49## Usage with options
50
51```js
52function onClick() {}
53
54console.log(prettyFormat(onClick));
55/*
56[Function onClick]
57*/
58
59const options = {
60 printFunctionName: false,
61};
62console.log(prettyFormat(onClick, options));
63/*
64[Function]
65*/
66```
67
68<!-- prettier-ignore -->
69| key | type | default | description |
70| :-------------------- | :-------- | :--------- | :------------------------------------------------------ |
71| `callToJSON` | `boolean` | `true` | call `toJSON` method (if it exists) on objects |
72| `compareKeys` | `function`| `undefined`| compare function used when sorting object keys |
73| `escapeRegex` | `boolean` | `false` | escape special characters in regular expressions |
74| `escapeString` | `boolean` | `true` | escape special characters in strings |
75| `highlight` | `boolean` | `false` | highlight syntax with colors in terminal (some plugins) |
76| `indent` | `number` | `2` | spaces in each level of indentation |
77| `maxDepth` | `number` | `Infinity` | levels to print in arrays, objects, elements, and so on |
78| `min` | `boolean` | `false` | minimize added space: no indentation nor line breaks |
79| `plugins` | `array` | `[]` | plugins to serialize application-specific data types |
80| `printBasicPrototype` | `boolean` | `false` | print the prototype for plain objects and arrays |
81| `printFunctionName` | `boolean` | `true` | include or omit the name of a function |
82| `theme` | `object` | | colors to highlight syntax in terminal |
83
84Property values of `theme` are from [ansi-styles colors](https://github.com/chalk/ansi-styles#colors)
85
86```js
87const DEFAULT_THEME = {
88 comment: 'gray',
89 content: 'reset',
90 prop: 'yellow',
91 tag: 'cyan',
92 value: 'green',
93};
94```
95
96## Usage with plugins
97
98The `pretty-format` package provides some built-in plugins, including:
99
100- `ReactElement` for elements from `react`
101- `ReactTestComponent` for test objects from `react-test-renderer`
102
103```js
104// CommonJS
105const React = require('react');
106const renderer = require('react-test-renderer');
107const {format: prettyFormat, plugins} = require('pretty-format');
108
109const {ReactElement, ReactTestComponent} = plugins;
110```
111
112```js
113// ES2015 modules and destructuring assignment
114import React from 'react';
115import renderer from 'react-test-renderer';
116import {plugins, format as prettyFormat} from 'pretty-format';
117
118const {ReactElement, ReactTestComponent} = plugins;
119```
120
121```js
122const onClick = () => {};
123const element = React.createElement('button', {onClick}, 'Hello World');
124
125const formatted1 = prettyFormat(element, {
126 plugins: [ReactElement],
127 printFunctionName: false,
128});
129const formatted2 = prettyFormat(renderer.create(element).toJSON(), {
130 plugins: [ReactTestComponent],
131 printFunctionName: false,
132});
133/*
134<button
135 onClick=[Function]
136>
137 Hello World
138</button>
139*/
140```
141
142## Usage in Jest
143
144For snapshot tests, Jest uses `pretty-format` with options that include some of its built-in plugins. For this purpose, plugins are also known as **snapshot serializers**.
145
146To serialize application-specific data types, you can add modules to `devDependencies` of a project, and then:
147
148In an **individual** test file, you can add a module as follows. It precedes any modules from Jest configuration.
149
150```js
151import serializer from 'my-serializer-module';
152expect.addSnapshotSerializer(serializer);
153
154// tests which have `expect(value).toMatchSnapshot()` assertions
155```
156
157For **all** test files, you can specify modules in Jest configuration. They precede built-in plugins for React, HTML, and Immutable.js data types. For example, in a `package.json` file:
158
159```json
160{
161 "jest": {
162 "snapshotSerializers": ["my-serializer-module"]
163 }
164}
165```
166
167## Writing plugins
168
169A plugin is a JavaScript object.
170
171If `options` has a `plugins` array: for the first plugin whose `test(val)` method returns a truthy value, then `prettyFormat(val, options)` returns the result from either:
172
173- `serialize(val, …)` method of the **improved** interface (available in **version 21** or later)
174- `print(val, …)` method of the **original** interface (if plugin does not have `serialize` method)
175
176### test
177
178Write `test` so it can receive `val` argument of any type. To serialize **objects** which have certain properties, then a guarded expression like `val != null && …` or more concise `val && …` prevents the following errors:
179
180- `TypeError: Cannot read property 'whatever' of null`
181- `TypeError: Cannot read property 'whatever' of undefined`
182
183For example, `test` method of built-in `ReactElement` plugin:
184
185```js
186const elementSymbol = Symbol.for('react.element');
187const test = val => val && val.$$typeof === elementSymbol;
188```
189
190Pay attention to efficiency in `test` because `pretty-format` calls it often.
191
192### serialize
193
194The **improved** interface is available in **version 21** or later.
195
196Write `serialize` to return a string, given the arguments:
197
198- `val` which “passed the test”
199- unchanging `config` object: derived from `options`
200- current `indentation` string: concatenate to `indent` from `config`
201- current `depth` number: compare to `maxDepth` from `config`
202- current `refs` array: find circular references in objects
203- `printer` callback function: serialize children
204
205### config
206
207<!-- prettier-ignore -->
208| key | type | description |
209| :------------------ | :-------- | :------------------------------------------------------ |
210| `callToJSON` | `boolean` | call `toJSON` method (if it exists) on objects |
211| `compareKeys` | `function`| compare function used when sorting object keys |
212| `colors` | `Object` | escape codes for colors to highlight syntax |
213| `escapeRegex` | `boolean` | escape special characters in regular expressions |
214| `escapeString` | `boolean` | escape special characters in strings |
215| `indent` | `string` | spaces in each level of indentation |
216| `maxDepth` | `number` | levels to print in arrays, objects, elements, and so on |
217| `min` | `boolean` | minimize added space: no indentation nor line breaks |
218| `plugins` | `array` | plugins to serialize application-specific data types |
219| `printFunctionName` | `boolean` | include or omit the name of a function |
220| `spacingInner` | `strong` | spacing to separate items in a list |
221| `spacingOuter` | `strong` | spacing to enclose a list of items |
222
223Each property of `colors` in `config` corresponds to a property of `theme` in `options`:
224
225- the key is the same (for example, `tag`)
226- the value in `colors` is a object with `open` and `close` properties whose values are escape codes from [ansi-styles](https://github.com/chalk/ansi-styles) for the color value in `theme` (for example, `'cyan'`)
227
228Some properties in `config` are derived from `min` in `options`:
229
230- `spacingInner` and `spacingOuter` are **newline** if `min` is `false`
231- `spacingInner` is **space** and `spacingOuter` is **empty string** if `min` is `true`
232
233### Example of serialize and test
234
235This plugin is a pattern you can apply to serialize composite data types. Side note: `pretty-format` does not need a plugin to serialize arrays.
236
237```js
238// We reused more code when we factored out a function for child items
239// that is independent of depth, name, and enclosing punctuation (see below).
240const SEPARATOR = ',';
241function serializeItems(items, config, indentation, depth, refs, printer) {
242 if (items.length === 0) {
243 return '';
244 }
245 const indentationItems = indentation + config.indent;
246 return (
247 config.spacingOuter +
248 items
249 .map(
250 item =>
251 indentationItems +
252 printer(item, config, indentationItems, depth, refs), // callback
253 )
254 .join(SEPARATOR + config.spacingInner) +
255 (config.min ? '' : SEPARATOR) + // following the last item
256 config.spacingOuter +
257 indentation
258 );
259}
260
261const plugin = {
262 test(val) {
263 return Array.isArray(val);
264 },
265 serialize(array, config, indentation, depth, refs, printer) {
266 const name = array.constructor.name;
267 return ++depth > config.maxDepth
268 ? '[' + name + ']'
269 : (config.min ? '' : name + ' ') +
270 '[' +
271 serializeItems(array, config, indentation, depth, refs, printer) +
272 ']';
273 },
274};
275```
276
277```js
278const val = {
279 filter: 'completed',
280 items: [
281 {
282 text: 'Write test',
283 completed: true,
284 },
285 {
286 text: 'Write serialize',
287 completed: true,
288 },
289 ],
290};
291```
292
293```js
294console.log(
295 prettyFormat(val, {
296 plugins: [plugin],
297 }),
298);
299/*
300Object {
301 "filter": "completed",
302 "items": Array [
303 Object {
304 "completed": true,
305 "text": "Write test",
306 },
307 Object {
308 "completed": true,
309 "text": "Write serialize",
310 },
311 ],
312}
313*/
314```
315
316```js
317console.log(
318 prettyFormat(val, {
319 indent: 4,
320 plugins: [plugin],
321 }),
322);
323/*
324Object {
325 "filter": "completed",
326 "items": Array [
327 Object {
328 "completed": true,
329 "text": "Write test",
330 },
331 Object {
332 "completed": true,
333 "text": "Write serialize",
334 },
335 ],
336}
337*/
338```
339
340```js
341console.log(
342 prettyFormat(val, {
343 maxDepth: 1,
344 plugins: [plugin],
345 }),
346);
347/*
348Object {
349 "filter": "completed",
350 "items": [Array],
351}
352*/
353```
354
355```js
356console.log(
357 prettyFormat(val, {
358 min: true,
359 plugins: [plugin],
360 }),
361);
362/*
363{"filter": "completed", "items": [{"completed": true, "text": "Write test"}, {"completed": true, "text": "Write serialize"}]}
364*/
365```
366
367### print
368
369The **original** interface is adequate for plugins:
370
371- that **do not** depend on options other than `highlight` or `min`
372- that **do not** depend on `depth` or `refs` in recursive traversal, and
373- if values either
374 - do **not** require indentation, or
375 - do **not** occur as children of JavaScript data structures (for example, array)
376
377Write `print` to return a string, given the arguments:
378
379- `val` which “passed the test”
380- current `printer(valChild)` callback function: serialize children
381- current `indenter(lines)` callback function: indent lines at the next level
382- unchanging `config` object: derived from `options`
383- unchanging `colors` object: derived from `options`
384
385The 3 properties of `config` are `min` in `options` and:
386
387- `spacing` and `edgeSpacing` are **newline** if `min` is `false`
388- `spacing` is **space** and `edgeSpacing` is **empty string** if `min` is `true`
389
390Each property of `colors` corresponds to a property of `theme` in `options`:
391
392- the key is the same (for example, `tag`)
393- the value in `colors` is a object with `open` and `close` properties whose values are escape codes from [ansi-styles](https://github.com/chalk/ansi-styles) for the color value in `theme` (for example, `'cyan'`)
394
395### Example of print and test
396
397This plugin prints functions with the **number of named arguments** excluding rest argument.
398
399```js
400const plugin = {
401 print(val) {
402 return `[Function ${val.name || 'anonymous'} ${val.length}]`;
403 },
404 test(val) {
405 return typeof val === 'function';
406 },
407};
408```
409
410```js
411const val = {
412 onClick(event) {},
413 render() {},
414};
415
416prettyFormat(val, {
417 plugins: [plugin],
418});
419/*
420Object {
421 "onClick": [Function onClick 1],
422 "render": [Function render 0],
423}
424*/
425
426prettyFormat(val);
427/*
428Object {
429 "onClick": [Function onClick],
430 "render": [Function render],
431}
432*/
433```
434
435This plugin **ignores** the `printFunctionName` option. That limitation of the original `print` interface is a reason to use the improved `serialize` interface, described above.
436
437```js
438prettyFormat(val, {
439 plugins: [pluginOld],
440 printFunctionName: false,
441});
442/*
443Object {
444 "onClick": [Function onClick 1],
445 "render": [Function render 0],
446}
447*/
448
449prettyFormat(val, {
450 printFunctionName: false,
451});
452/*
453Object {
454 "onClick": [Function],
455 "render": [Function],
456}
457*/
458```