From 58db6404d3fea76525130165440b28c1455b43ca Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Mon, 24 Jul 2017 13:18:46 -0400 Subject: [PATCH 01/11] Add alternative serialize API for pretty-format plugins --- .../__snapshots__/react.test.js.snap | 8 +- .../src/__tests__/pretty_format.test.js | 85 +++++++++- .../pretty-format/src/__tests__/react.test.js | 145 +++++++++++++--- packages/pretty-format/src/index.js | 51 +++--- .../src/plugins/react_element.js | 158 +++++++++++------- .../src/plugins/react_test_component.js | 155 ++++++++++------- types/PrettyFormat.js | 33 +++- 7 files changed, 448 insertions(+), 187 deletions(-) diff --git a/packages/pretty-format/src/__tests__/__snapshots__/react.test.js.snap b/packages/pretty-format/src/__tests__/__snapshots__/react.test.js.snap index 712c798afe0d..827d083ea5a2 100644 --- a/packages/pretty-format/src/__tests__/__snapshots__/react.test.js.snap +++ b/packages/pretty-format/src/__tests__/__snapshots__/react.test.js.snap @@ -3,9 +3,9 @@ exports[`ReactElement plugin highlights syntax 1`] = ` " prop={ - > +
mouse - > + rat
@@ -24,9 +24,9 @@ exports[`ReactElement plugin highlights syntax with color from theme option 1`] exports[`ReactTestComponent plugin highlights syntax 1`] = ` " prop={ - > +
mouse - > + rat
diff --git a/packages/pretty-format/src/__tests__/pretty_format.test.js b/packages/pretty-format/src/__tests__/pretty_format.test.js index 62b291b33a36..eac6c8f397cd 100644 --- a/packages/pretty-format/src/__tests__/pretty_format.test.js +++ b/packages/pretty-format/src/__tests__/pretty_format.test.js @@ -280,6 +280,45 @@ describe('prettyFormat()', () => { expect(prettyFormat('\\ \\\\')).toEqual('"\\\\ \\\\\\\\"'); }); + it('prints a multiline string', () => { + const val = ['line 1', 'line 2', 'line 3'].join('\n'); + expect(prettyFormat(val)).toEqual('"' + val + '"'); + }); + + it('prints a multiline string as value of object property', () => { + const polyline = { + props: { + id: 'J', + points: ['0.5,0.460', '0.5,0.875', '0.25,0.875'].join('\n'), + }, + type: 'polyline', + }; + const val = { + props: { + children: polyline, + }, + type: 'svg', + }; + expect(prettyFormat(val)).toEqual( + [ + 'Object {', + ' "props": Object {', + ' "children": Object {', + ' "props": Object {', + ' "id": "J",', + ' "points": "0.5,0.460', + '0.5,0.875', + '0.25,0.875",', + ' },', + ' "type": "polyline",', + ' },', + ' },', + ' "type": "svg",', + '}', + ].join('\n'), + ); + }); + it('prints a symbol', () => { const val = Symbol('symbol'); expect(prettyFormat(val)).toEqual('Symbol(symbol)'); @@ -321,11 +360,47 @@ describe('prettyFormat()', () => { ); }); - it('can customize indent', () => { - const val = {prop: 'value'}; - expect(prettyFormat(val, {indent: 4})).toEqual( - 'Object {\n "prop": "value",\n}', - ); + describe('indent option', () => { + const val = [ + { + id: '8658c1d0-9eda-4a90-95e1-8001e8eb6036', + text: 'Add alternative serialize API for pretty-format plugins', + type: 'ADD_TODO', + }, + { + id: '8658c1d0-9eda-4a90-95e1-8001e8eb6036', + type: 'TOGGLE_TODO', + }, + ]; + const expected = [ + 'Array [', + ' Object {', + ' "id": "8658c1d0-9eda-4a90-95e1-8001e8eb6036",', + ' "text": "Add alternative serialize API for pretty-format plugins",', + ' "type": "ADD_TODO",', + ' },', + ' Object {', + ' "id": "8658c1d0-9eda-4a90-95e1-8001e8eb6036",', + ' "type": "TOGGLE_TODO",', + ' },', + ']', + ].join('\n'); + test('default implicit: 2 spaces', () => { + expect(prettyFormat(val)).toEqual(expected); + }); + test('default explicit: 2 spaces', () => { + expect(prettyFormat(val, {indent: 2})).toEqual(expected); + }); + test('non-default: 0 spaces', () => { + expect(prettyFormat(val, {indent: 0})).toEqual( + expected.replace(/ {2}/g, ''), + ); + }); + test('non-default: 4 spaces', () => { + expect(prettyFormat(val, {indent: 4})).toEqual( + expected.replace(/ {2}/g, ' '), + ); + }); }); it('can customize the max depth', () => { diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 871ccb7f0f15..d079f824afe6 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -13,29 +13,33 @@ const prettyFormat = require('../'); const ReactTestComponent = require('../plugins/react_test_component'); const ReactElement = require('../plugins/react_element'); -function assertPrintedJSX(actual, expected, opts) { - expect( - prettyFormat( - actual, - Object.assign( - { - plugins: [ReactElement], - }, - opts, - ), +const prettyFormatElementPlugin = (element, options) => + prettyFormat( + element, + Object.assign( + { + plugins: [ReactElement], + }, + options, ), - ).toEqual(expected); - expect( - prettyFormat( - renderer.create(actual).toJSON(), - Object.assign( - { - plugins: [ReactTestComponent, ReactElement], - }, - opts, - ), + ); + +const prettyFormatBothPlugins = (object, options) => + prettyFormat( + object, + Object.assign( + { + plugins: [ReactTestComponent, ReactElement], + }, + options, ), - ).toEqual(expected); + ); + +function assertPrintedJSX(val, formatted, options) { + expect(prettyFormatElementPlugin(val, options)).toEqual(formatted); + expect( + prettyFormatBothPlugins(renderer.create(val).toJSON(), options), + ).toEqual(formatted); } test('supports a single element with no props or children', () => { @@ -70,6 +74,28 @@ test('supports props with strings', () => { ); }); +test('supports props with multiline strings', () => { + const val = React.createElement( + 'svg', + null, + React.createElement('polyline', { + id: 'J', + points: ['0.5,0.460', '0.5,0.875', '0.25,0.875'].join('\n'), + }), + ); + const formatted = [ + '', + ' ', + '', + ].join('\n'); + assertPrintedJSX(val, formatted); +}); + test('supports props with numbers', () => { assertPrintedJSX( React.createElement('Mouse', {size: 5}), @@ -292,7 +318,82 @@ test('supports a single element with React elements with array children', () => ); }); -test('uses the supplied line seperator for min mode', () => { +test('supports array of elements', () => { + const val = [ + React.createElement('dt', null, 'jest'), + React.createElement('dd', null, 'to talk in a playful manner'), + React.createElement( + 'dd', + {style: {color: '#99424F'}}, + 'painless JavaScript testing', + ), + ]; + const formatted = [ + 'Array [', + '
', + ' jest', + '
,', + '
', + ' to talk in a playful manner', + '
,', + ' ', + ' painless JavaScript testing', + ' ,', + ']', + ].join('\n'); + expect(prettyFormatElementPlugin(val)).toEqual(formatted); + expect( + prettyFormatBothPlugins( + val.map(element => renderer.create(element).toJSON()), + ), + ).toEqual(formatted); +}); + +describe('indent option', () => { + const val = React.createElement( + 'ul', + null, + React.createElement( + 'li', + {style: {color: 'green', textDecoration: 'none'}}, + 'Test indent option', + ), + ); + const formatted = [ + '
    ', + ' ', + ' Test indent option', + ' ', + '
', + ].join('\n'); + test('default implicit: 2 spaces', () => { + assertPrintedJSX(val, formatted); + }); + test('default explicit: 2 spaces', () => { + assertPrintedJSX(val, formatted, {indent: 2}); + }); + test('non-default: 0 spaces', () => { + assertPrintedJSX(val, formatted.replace(/ {2}/g, ''), {indent: 0}); + }); + test('non-default: 4 spaces', () => { + assertPrintedJSX(val, formatted.replace(/ {2}/g, ' '), {indent: 4}); + }); +}); + +test('min option', () => { assertPrintedJSX( React.createElement( 'Mouse', diff --git a/packages/pretty-format/src/index.js b/packages/pretty-format/src/index.js index b2a25ffc9737..16d12352e062 100644 --- a/packages/pretty-format/src/index.js +++ b/packages/pretty-format/src/index.js @@ -377,30 +377,33 @@ function printPlugin( depth: number, refs: Refs, ): string { - function boundPrint(val) { - return print(val, config, indentation, depth, refs); - } - - function boundIndent(str) { - const indentationNext = indentation + config.indent; - return ( - indentationNext + str.replace(NEWLINE_REGEXP, '\n' + indentationNext) - ); - } - - const opts = { - edgeSpacing: config.spacingOuter, - min: config.min, - spacing: config.spacingInner, - }; - - const printed = plugin.print( - val, - boundPrint, - boundIndent, - opts, - config.colors, - ); + const printed = plugin.serialize + ? plugin.serialize( + val, + config, + (valChild, indentationChild, depthChild, refsChild) => + print(valChild, config, indentationChild, depthChild, refsChild), + indentation, + depth, + refs, + ) + : plugin.print( + val, + valChild => print(valChild, config, indentation, depth, refs), + str => { + const indentationNext = indentation + config.indent; + return ( + indentationNext + + str.replace(NEWLINE_REGEXP, '\n' + indentationNext) + ); + }, + { + edgeSpacing: config.spacingOuter, + min: config.min, + spacing: config.spacingInner, + }, + config.colors, + ); if (typeof printed !== 'string') { throw new Error( `pretty-format: Plugin must return type "string" but instead returned "${typeof printed}".`, diff --git a/packages/pretty-format/src/plugins/react_element.js b/packages/pretty-format/src/plugins/react_element.js index d4be69952fa5..36c7ad0d3d04 100644 --- a/packages/pretty-format/src/plugins/react_element.js +++ b/packages/pretty-format/src/plugins/react_element.js @@ -8,17 +8,11 @@ * @flow */ -import type { - Colors, - Indent, - PluginOptions, - Print, - Plugin, -} from 'types/PrettyFormat'; +import type {Config, NewPlugin, Printer, Refs} from 'types/PrettyFormat'; import escapeHTML from './lib/escape_html'; -const reactElement = Symbol.for('react.element'); +const elementSymbol = Symbol.for('react.element'); function traverseChildren(opaqueChildren, cb) { if (Array.isArray(opaqueChildren)) { @@ -28,43 +22,63 @@ function traverseChildren(opaqueChildren, cb) { } } -function printChildren(flatChildren, print, indent, colors, opts) { - return flatChildren - .map(node => { - if (typeof node === 'string') { - return colors.content.open + escapeHTML(node) + colors.content.close; - } else { - return print(node); - } - }) - .join(opts.edgeSpacing); +function printChildren( + children: Array, + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string { + const colors = config.colors; + return children + .map( + child => + config.spacingOuter + + indentation + + (typeof child === 'string' + ? colors.content.open + escapeHTML(child) + colors.content.close + : printer(child, indentation, depth, refs)), + ) + .join(''); } -function printProps(props, print, indent, colors, opts) { - return Object.keys(props) +function printProps( + keys: Array, + props: Object, + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string { + const indentationNext = indentation + config.indent; + const colors = config.colors; + return keys .sort() - .map(name => { - if (name === 'children') { - return ''; - } - - const prop = props[name]; - let printed = print(prop); + .map(key => { + const value = props[key]; + let printed = printer(value, indentationNext, depth, refs); - if (typeof prop !== 'string') { + if (typeof value !== 'string') { if (printed.indexOf('\n') !== -1) { printed = - '{' + - opts.edgeSpacing + - indent(indent(printed) + opts.edgeSpacing + '}'); - } else { - printed = '{' + printed + '}'; + config.spacingOuter + + indentationNext + + printed + + config.spacingOuter + + indentation; } + printed = '{' + printed + '}'; } return ( - opts.spacing + - indent(colors.prop.open + name + colors.prop.close + '=') + + config.spacingInner + + indentation + + colors.prop.open + + key + + colors.prop.close + + '=' + colors.value.open + printed + colors.value.close @@ -73,14 +87,15 @@ function printProps(props, print, indent, colors, opts) { .join(''); } -export const print = ( +export const serialize = ( element: React$Element<*>, - print: Print, - indent: Indent, - opts: PluginOptions, - colors: Colors, -) => { - let result = colors.tag.open + '<'; + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string => { + const tag = config.colors.tag; let elementName; if (typeof element.type === 'string') { elementName = element.type; @@ -89,45 +104,58 @@ export const print = ( } else { elementName = 'Unknown'; } - result += elementName + colors.tag.close; - result += printProps(element.props, print, indent, colors, opts); + let result = tag.open + '<' + elementName; - const opaqueChildren = element.props.children; - const hasProps = !!Object.keys(element.props).filter( - propName => propName !== 'children', - ).length; - const closeInNewLine = hasProps && !opts.min; + const keys = Object.keys(element.props).filter(key => key !== 'children'); + const hasProps = keys.length !== 0; + if (hasProps) { + result += + tag.close + + printProps( + keys, + element.props, + config, + printer, + indentation + config.indent, + depth, + refs, + ) + + config.spacingOuter + + indentation + + tag.open; + } + const opaqueChildren = element.props.children; if (opaqueChildren) { const flatChildren = []; traverseChildren(opaqueChildren, child => { flatChildren.push(child); }); - const children = printChildren(flatChildren, print, indent, colors, opts); result += - colors.tag.open + - (closeInNewLine ? '\n' : '') + '>' + - colors.tag.close + - opts.edgeSpacing + - indent(children) + - opts.edgeSpacing + - colors.tag.open + + tag.close + + printChildren( + flatChildren, + config, + printer, + indentation + config.indent, + depth, + refs, + ) + + config.spacingOuter + + indentation + + tag.open + '' + - colors.tag.close; + tag.close; } else { - result += - colors.tag.open + (closeInNewLine ? '\n' : ' ') + '/>' + colors.tag.close; + result += (hasProps && !config.min ? '' : ' ') + '/>' + tag.close; } return result; }; -// Disabling lint rule as we don't know type ahead of time. -/* eslint-disable flowtype/no-weak-types */ -export const test = (object: any) => object && object.$$typeof === reactElement; -/* eslint-enable flowtype/no-weak-types */ +export const test = (val: any) => val && val.$$typeof === elementSymbol; -export default ({print, test}: Plugin); +export default ({serialize, test}: NewPlugin); diff --git a/packages/pretty-format/src/plugins/react_test_component.js b/packages/pretty-format/src/plugins/react_test_component.js index 622cdd93b3ba..de8e386c03c8 100644 --- a/packages/pretty-format/src/plugins/react_test_component.js +++ b/packages/pretty-format/src/plugins/react_test_component.js @@ -9,58 +9,75 @@ */ import type { - Colors, - Indent, - PluginOptions, - Print, - Plugin, + Config, + Printer, + NewPlugin, ReactTestObject, ReactTestChild, + Refs, } from 'types/PrettyFormat'; import escapeHTML from './lib/escape_html'; -const reactTestInstance = Symbol.for('react.test.json'); +const testSymbol = Symbol.for('react.test.json'); function printChildren( children: Array, - print, - indent, - colors, - opts, -) { + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string { + const colors = config.colors; return children - .map(node => { - if (typeof node === 'string') { - return colors.content.open + escapeHTML(node) + colors.content.close; - } else { - return print(node); - } - }) - .join(opts.edgeSpacing); + .map( + child => + config.spacingOuter + + indentation + + (typeof child === 'string' + ? colors.content.open + escapeHTML(child) + colors.content.close + : printer(child, indentation, depth, refs)), + ) + .join(''); } -function printProps(props: Object, print, indent, colors, opts) { - return Object.keys(props) +function printProps( + keys: Array, + props: Object, + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string { + const indentationNext = indentation + config.indent; + const colors = config.colors; + return keys .sort() - .map(name => { - const prop = props[name]; - let printed = print(prop); + .map(key => { + const value = props[key]; + let printed = printer(value, indentationNext, depth, refs); - if (typeof prop !== 'string') { + if (typeof value !== 'string') { if (printed.indexOf('\n') !== -1) { printed = - '{' + - opts.edgeSpacing + - indent(indent(printed) + opts.edgeSpacing + '}'); - } else { - printed = '{' + printed + '}'; + config.spacingOuter + + indentationNext + + printed + + config.spacingOuter + + indentation; } + printed = '{' + printed + '}'; } return ( - opts.spacing + - indent(colors.prop.open + name + colors.prop.close + '=') + + config.spacingInner + + indentation + + colors.prop.open + + key + + colors.prop.close + + '=' + colors.value.open + printed + colors.value.close @@ -69,51 +86,65 @@ function printProps(props: Object, print, indent, colors, opts) { .join(''); } -export const print = ( +export const serialize = ( instance: ReactTestObject, - print: Print, - indent: Indent, - opts: PluginOptions, - colors: Colors, -) => { - let closeInNewLine = false; - let result = colors.tag.open + '<' + instance.type + colors.tag.close; + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, +): string => { + const tag = config.colors.tag; + let result = tag.open + '<' + instance.type; + let hasProps = false; if (instance.props) { - closeInNewLine = !!Object.keys(instance.props).length && !opts.min; - result += printProps(instance.props, print, indent, colors, opts); + const keys = Object.keys(instance.props); + hasProps = keys.length !== 0; + if (hasProps) { + result += + tag.close + + printProps( + keys, + instance.props, + config, + printer, + indentation + config.indent, + depth, + refs, + ) + + config.spacingOuter + + indentation + + tag.open; + } } if (instance.children) { - const children = printChildren( - instance.children, - print, - indent, - colors, - opts, - ); result += - colors.tag.open + - (closeInNewLine ? '\n' : '') + '>' + - colors.tag.close + - opts.edgeSpacing + - indent(children) + - opts.edgeSpacing + - colors.tag.open + + tag.close + + printChildren( + instance.children, + config, + printer, + indentation + config.indent, + depth, + refs, + ) + + config.spacingOuter + + indentation + + tag.open + '' + - colors.tag.close; + tag.close; } else { - result += - colors.tag.open + (closeInNewLine ? '\n' : ' ') + '/>' + colors.tag.close; + result += (hasProps && !config.min ? '' : ' ') + '/>' + tag.close; } return result; }; -export const test = (object: Object) => - object && object.$$typeof === reactTestInstance; +export const test = (val: any) => val && val.$$typeof === testSymbol; -export default ({print, test}: Plugin); +export default ({serialize, test}: NewPlugin); diff --git a/types/PrettyFormat.js b/types/PrettyFormat.js index cd8ce0fa6db0..5a5358f63ac9 100644 --- a/types/PrettyFormat.js +++ b/types/PrettyFormat.js @@ -73,22 +73,45 @@ export type Config = {| spacingOuter: string, |}; +export type Printer = ( + val: any, + indentation: string, + depth: number, + refs: Refs, +) => string; + +export type Test = any => boolean; + +export type NewPlugin = {| + serialize: ( + val: any, + config: Config, + printer: Printer, + indentation: string, + depth: number, + refs: Refs, + ) => string, + test: Test, +|}; + export type PluginOptions = {| edgeSpacing: string, min: boolean, spacing: string, |}; -export type Plugin = { +export type OldPlugin = {| print: ( val: any, - serialize: Print, + print: Print, indent: Indent, - opts: PluginOptions, + options: PluginOptions, colors: Colors, ) => string, - test: any => boolean, -}; + test: Test, +|}; + +export type Plugin = NewPlugin | OldPlugin; export type Plugins = Array; From a5f383ca3f7607ee0567da1c8148fca7a6e7b066 Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Mon, 24 Jul 2017 13:45:18 -0400 Subject: [PATCH 02/11] Fix logic in ReactElement plugin and add test for zero number child --- packages/pretty-format/src/__tests__/react.test.js | 9 ++++++++- packages/pretty-format/src/plugins/react_element.js | 11 +++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index d079f824afe6..766e86b3d79a 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -53,13 +53,20 @@ test('supports a single element with no props', () => { ); }); -test('supports a single element with number children', () => { +test('supports a single element with nonzero number child', () => { assertPrintedJSX( React.createElement('Mouse', null, 4), '\n 4\n', ); }); +test('supports a single element with zero number child', () => { + assertPrintedJSX( + React.createElement('Mouse', null, 0), + '\n 0\n', + ); +}); + test('supports a single element with mixed children', () => { assertPrintedJSX( React.createElement('Mouse', null, [[1, null], 2, undefined, [false, [3]]]), diff --git a/packages/pretty-format/src/plugins/react_element.js b/packages/pretty-format/src/plugins/react_element.js index 36c7ad0d3d04..1fd6ba26a33c 100644 --- a/packages/pretty-format/src/plugins/react_element.js +++ b/packages/pretty-format/src/plugins/react_element.js @@ -125,12 +125,11 @@ export const serialize = ( tag.open; } - const opaqueChildren = element.props.children; - if (opaqueChildren) { - const flatChildren = []; - traverseChildren(opaqueChildren, child => { - flatChildren.push(child); - }); + const flatChildren = []; + traverseChildren(element.props.children, child => { + flatChildren.push(child); + }); + if (flatChildren.length !== 0) { result += '>' + tag.close + From 2ff0244ab796e89f7f2f297d1e653c21b2c893dc Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Tue, 25 Jul 2017 16:57:25 -0400 Subject: [PATCH 03/11] Add test for empty string child --- packages/pretty-format/src/__tests__/react.test.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 766e86b3d79a..dad3d510b0a7 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -46,14 +46,14 @@ test('supports a single element with no props or children', () => { assertPrintedJSX(React.createElement('Mouse'), ''); }); -test('supports a single element with no props', () => { +test('supports a single element with non-empty string child', () => { assertPrintedJSX( React.createElement('Mouse', null, 'Hello World'), '\n Hello World\n', ); }); -test('supports a single element with nonzero number child', () => { +test('supports a single element with non-zero number child', () => { assertPrintedJSX( React.createElement('Mouse', null, 4), '\n 4\n', @@ -67,6 +67,13 @@ test('supports a single element with zero number child', () => { ); }); +test('supports a single element with empty string child', () => { + assertPrintedJSX( + React.createElement('Mouse', null, ''), + '\n \n', + ); +}); + test('supports a single element with mixed children', () => { assertPrintedJSX( React.createElement('Mouse', null, [[1, null], 2, undefined, [false, [3]]]), From 05fc6f4b958d1c3b30ba85ec7716036c7df356ea Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Wed, 26 Jul 2017 11:27:54 -0400 Subject: [PATCH 04/11] Rename 2 helper functions and use in more places --- .../pretty-format/src/__tests__/react.test.js | 61 ++++++++----------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index dad3d510b0a7..6804c7fa501a 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -13,7 +13,7 @@ const prettyFormat = require('../'); const ReactTestComponent = require('../plugins/react_test_component'); const ReactElement = require('../plugins/react_element'); -const prettyFormatElementPlugin = (element, options) => +const formatElement = (element, options) => prettyFormat( element, Object.assign( @@ -24,7 +24,7 @@ const prettyFormatElementPlugin = (element, options) => ), ); -const prettyFormatBothPlugins = (object, options) => +const formatTestObject = (object, options) => prettyFormat( object, Object.assign( @@ -35,11 +35,11 @@ const prettyFormatBothPlugins = (object, options) => ), ); -function assertPrintedJSX(val, formatted, options) { - expect(prettyFormatElementPlugin(val, options)).toEqual(formatted); - expect( - prettyFormatBothPlugins(renderer.create(val).toJSON(), options), - ).toEqual(formatted); +function assertPrintedJSX(val, expected, options) { + expect(formatElement(val, options)).toEqual(expected); + expect(formatTestObject(renderer.create(val).toJSON(), options)).toEqual( + expected, + ); } test('supports a single element with no props or children', () => { @@ -53,6 +53,13 @@ test('supports a single element with non-empty string child', () => { ); }); +test('supports a single element with empty string child', () => { + assertPrintedJSX( + React.createElement('Mouse', null, ''), + '\n \n', + ); +}); + test('supports a single element with non-zero number child', () => { assertPrintedJSX( React.createElement('Mouse', null, 4), @@ -67,13 +74,6 @@ test('supports a single element with zero number child', () => { ); }); -test('supports a single element with empty string child', () => { - assertPrintedJSX( - React.createElement('Mouse', null, ''), - '\n \n', - ); -}); - test('supports a single element with mixed children', () => { assertPrintedJSX( React.createElement('Mouse', null, [[1, null], 2, undefined, [false, [3]]]), @@ -289,11 +289,7 @@ test('supports Unknown element', () => { // Suppress React.createElement(undefined) console error const consoleError = console.error; console.error = jest.fn(); - expect( - prettyFormat(React.createElement(undefined), { - plugins: [ReactElement], - }), - ).toEqual(''); + expect(formatElement(React.createElement(undefined))).toEqual(''); console.error = consoleError; }); @@ -361,11 +357,9 @@ test('supports array of elements', () => { ' ,', ']', ].join('\n'); - expect(prettyFormatElementPlugin(val)).toEqual(formatted); + expect(formatElement(val)).toEqual(formatted); expect( - prettyFormatBothPlugins( - val.map(element => renderer.create(element).toJSON()), - ), + formatTestObject(val.map(element => renderer.create(element).toJSON())), ).toEqual(formatted); }); @@ -437,9 +431,8 @@ test('ReactElement plugin highlights syntax', () => { ), }); expect( - prettyFormat(jsx, { + formatElement(jsx, { highlight: true, - plugins: [ReactElement], }), ).toMatchSnapshot(); }); @@ -454,9 +447,8 @@ test('ReactTestComponent plugin highlights syntax', () => { ), }); expect( - prettyFormat(renderer.create(jsx).toJSON(), { + formatTestObject(renderer.create(jsx).toJSON(), { highlight: true, - plugins: [ReactTestComponent, ReactElement], }), ).toMatchSnapshot(); }); @@ -468,9 +460,8 @@ test('throws if theme option is null', () => { 'Hello, Mouse!', ); expect(() => { - prettyFormat(jsx, { + formatElement(jsx, { highlight: true, - plugins: [ReactElement], theme: null, }); }).toThrow('pretty-format: Option "theme" must not be null.'); @@ -483,9 +474,8 @@ test('throws if theme option is not of type "object"', () => { {style: 'color:red'}, 'Hello, Mouse!', ); - prettyFormat(jsx, { + formatElement(jsx, { highlight: true, - plugins: [ReactElement], theme: 'beautiful', }); }).toThrow( @@ -500,9 +490,8 @@ test('throws if theme option has value that is undefined in ansi-styles', () => {style: 'color:red'}, 'Hello, Mouse!', ); - prettyFormat(jsx, { + formatElement(jsx, { highlight: true, - plugins: [ReactElement], theme: { content: 'unknown', prop: 'yellow', @@ -522,9 +511,8 @@ test('ReactElement plugin highlights syntax with color from theme option', () => 'Hello, Mouse!', ); expect( - prettyFormat(jsx, { + formatElement(jsx, { highlight: true, - plugins: [ReactElement], theme: { value: 'red', }, @@ -539,9 +527,8 @@ test('ReactTestComponent plugin highlights syntax with color from theme option', 'Hello, Mouse!', ); expect( - prettyFormat(renderer.create(jsx).toJSON(), { + formatTestObject(renderer.create(jsx).toJSON(), { highlight: true, - plugins: [ReactTestComponent, ReactElement], theme: { value: 'red', }, From ec3147ed1dd3607339facbebd4e7ce91b66f26fa Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Thu, 27 Jul 2017 09:37:39 -0400 Subject: [PATCH 05/11] Replace require paths to plugins with destructuring assignment --- packages/pretty-format/src/__tests__/react.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 6804c7fa501a..4cf68c7e49e2 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -10,8 +10,10 @@ const React = require('react'); const renderer = require('react-test-renderer'); const prettyFormat = require('../'); -const ReactTestComponent = require('../plugins/react_test_component'); -const ReactElement = require('../plugins/react_element'); +const { + ReactElement, + ReactTestComponent, +} = prettyFormat.plugins; const formatElement = (element, options) => prettyFormat( From ed873d62fb4a3e0e700a3a1689b2f104f52b4417 Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Thu, 27 Jul 2017 09:51:02 -0400 Subject: [PATCH 06/11] Add any type annotation to val arg of printPlugin --- packages/pretty-format/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pretty-format/src/index.js b/packages/pretty-format/src/index.js index 16d12352e062..140de3b86211 100644 --- a/packages/pretty-format/src/index.js +++ b/packages/pretty-format/src/index.js @@ -371,7 +371,7 @@ function printComplexValue( function printPlugin( plugin: Plugin, - val, + val: any, config: Config, indentation: string, depth: number, From 088ab74a02c045b2524ef441b69f15df7ba84ecd Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Thu, 27 Jul 2017 09:52:33 -0400 Subject: [PATCH 07/11] Replace overlooked occurrences of formatted with expected --- .../pretty-format/src/__tests__/react.test.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 4cf68c7e49e2..31340f07a5b4 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -99,7 +99,7 @@ test('supports props with multiline strings', () => { points: ['0.5,0.460', '0.5,0.875', '0.25,0.875'].join('\n'), }), ); - const formatted = [ + const expected = [ '', ' { ' />', '', ].join('\n'); - assertPrintedJSX(val, formatted); + assertPrintedJSX(val, expected); }); test('supports props with numbers', () => { @@ -340,7 +340,7 @@ test('supports array of elements', () => { 'painless JavaScript testing', ), ]; - const formatted = [ + const expected = [ 'Array [', '
', ' jest', @@ -359,10 +359,10 @@ test('supports array of elements', () => { ' ,', ']', ].join('\n'); - expect(formatElement(val)).toEqual(formatted); + expect(formatElement(val)).toEqual(expected); expect( formatTestObject(val.map(element => renderer.create(element).toJSON())), - ).toEqual(formatted); + ).toEqual(expected); }); describe('indent option', () => { @@ -375,7 +375,7 @@ describe('indent option', () => { 'Test indent option', ), ); - const formatted = [ + const expected = [ '
    ', ' { '
', ].join('\n'); test('default implicit: 2 spaces', () => { - assertPrintedJSX(val, formatted); + assertPrintedJSX(val, expected); }); test('default explicit: 2 spaces', () => { - assertPrintedJSX(val, formatted, {indent: 2}); + assertPrintedJSX(val, expected, {indent: 2}); }); test('non-default: 0 spaces', () => { - assertPrintedJSX(val, formatted.replace(/ {2}/g, ''), {indent: 0}); + assertPrintedJSX(val, expected.replace(/ {2}/g, ''), {indent: 0}); }); test('non-default: 4 spaces', () => { - assertPrintedJSX(val, formatted.replace(/ {2}/g, ' '), {indent: 4}); + assertPrintedJSX(val, expected.replace(/ {2}/g, ' '), {indent: 4}); }); }); From bb0083005b22b0fee8bbe3b5009478184f2f1e1e Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Thu, 27 Jul 2017 19:10:19 -0400 Subject: [PATCH 08/11] Fix pretty lint error --- packages/pretty-format/src/__tests__/react.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 31340f07a5b4..0d0b5c7a5e97 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -10,10 +10,7 @@ const React = require('react'); const renderer = require('react-test-renderer'); const prettyFormat = require('../'); -const { - ReactElement, - ReactTestComponent, -} = prettyFormat.plugins; +const {ReactElement, ReactTestComponent} = prettyFormat.plugins; const formatElement = (element, options) => prettyFormat( From 76ec48c14504f443dda358e57a84b1788b799bb0 Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Sat, 29 Jul 2017 08:24:32 -0400 Subject: [PATCH 09/11] Add comment and repeat to indent test --- .../src/__tests__/pretty_format.test.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/pretty-format/src/__tests__/pretty_format.test.js b/packages/pretty-format/src/__tests__/pretty_format.test.js index eac6c8f397cd..a1122068d4bf 100644 --- a/packages/pretty-format/src/__tests__/pretty_format.test.js +++ b/packages/pretty-format/src/__tests__/pretty_format.test.js @@ -391,14 +391,18 @@ describe('prettyFormat()', () => { test('default explicit: 2 spaces', () => { expect(prettyFormat(val, {indent: 2})).toEqual(expected); }); + + // Tests assume that no strings in val contain multiple adjacent spaces! test('non-default: 0 spaces', () => { - expect(prettyFormat(val, {indent: 0})).toEqual( - expected.replace(/ {2}/g, ''), + const indent = 0; + expect(prettyFormat(val, {indent})).toEqual( + expected.replace(/ {2}/g, ' '.repeat(indent)), ); }); test('non-default: 4 spaces', () => { - expect(prettyFormat(val, {indent: 4})).toEqual( - expected.replace(/ {2}/g, ' '), + const indent = 4; + expect(prettyFormat(val, {indent})).toEqual( + expected.replace(/ {2}/g, ' '.repeat(indent)), ); }); }); From 9550c22b2db04d82d1dec223cc982d3989447629 Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Sat, 29 Jul 2017 09:17:57 -0400 Subject: [PATCH 10/11] Add comment and repeat to indent test for react also --- packages/pretty-format/src/__tests__/react.test.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/pretty-format/src/__tests__/react.test.js b/packages/pretty-format/src/__tests__/react.test.js index 0d0b5c7a5e97..7bacad4148d6 100644 --- a/packages/pretty-format/src/__tests__/react.test.js +++ b/packages/pretty-format/src/__tests__/react.test.js @@ -392,11 +392,19 @@ describe('indent option', () => { test('default explicit: 2 spaces', () => { assertPrintedJSX(val, expected, {indent: 2}); }); + + // Tests assume that no strings in val contain multiple adjacent spaces! test('non-default: 0 spaces', () => { - assertPrintedJSX(val, expected.replace(/ {2}/g, ''), {indent: 0}); + const indent = 0; + assertPrintedJSX(val, expected.replace(/ {2}/g, ' '.repeat(indent)), { + indent, + }); }); test('non-default: 4 spaces', () => { - assertPrintedJSX(val, expected.replace(/ {2}/g, ' '), {indent: 4}); + const indent = 4; + assertPrintedJSX(val, expected.replace(/ {2}/g, ' '.repeat(indent)), { + indent, + }); }); }); From 90ea9cd567830a5d0621022ecfbb94d7a8c56551 Mon Sep 17 00:00:00 2001 From: Mark Pedrotti Date: Mon, 31 Jul 2017 12:04:04 -0400 Subject: [PATCH 11/11] Fix pretty lint error in html_element.test.js --- packages/pretty-format/src/__tests__/html_element.test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/pretty-format/src/__tests__/html_element.test.js b/packages/pretty-format/src/__tests__/html_element.test.js index f64ccd7698a2..18a33f265523 100644 --- a/packages/pretty-format/src/__tests__/html_element.test.js +++ b/packages/pretty-format/src/__tests__/html_element.test.js @@ -14,9 +14,7 @@ const prettyFormat = require('../'); const {HTMLElement} = prettyFormat.plugins; -const toPrettyPrintTo = require('./expect_util').getPrettyPrint([ - HTMLElement, -]); +const toPrettyPrintTo = require('./expect_util').getPrettyPrint([HTMLElement]); const expect: any = global.expect; expect.extend({toPrettyPrintTo});