diff --git a/packages/pretty-format/src/__tests__/html_element.test.js b/packages/pretty-format/src/__tests__/html_element.test.js index 18a33f265523..8d9ff42fc89a 100644 --- a/packages/pretty-format/src/__tests__/html_element.test.js +++ b/packages/pretty-format/src/__tests__/html_element.test.js @@ -61,6 +61,16 @@ describe('HTMLElement Plugin', () => { expect(parent).toPrettyPrintTo(''); }); + it('supports an HTML element with attribute and text content', () => { + const parent = document.createElement('div'); + parent.setAttribute('style', 'color: #99424F'); + parent.innerHTML = 'Jest'; + + expect(parent).toPrettyPrintTo( + '\n Jest\n', + ); + }); + it('supports an element with text content', () => { const parent = document.createElement('div'); parent.innerHTML = 'texty texty'; @@ -170,4 +180,68 @@ describe('HTMLElement Plugin', () => { '', ].join('\n')); }); + + it('supports indentation for array of elements', () => { + // For example, Array.prototype.slice.call(document.getElementsByTagName(…)) + const dd1 = document.createElement('dd'); + dd1.innerHTML = 'to talk in a playful manner'; + + const dd2 = document.createElement('dd'); + dd2.innerHTML = 'painless JavaScript testing'; + dd2.setAttribute('style', 'color: #99424F'); + + expect([dd1, dd2]).toPrettyPrintTo( + [ + 'Array [', + '
', + ' to talk in a playful manner', + '
,', + ' ', + ' painless JavaScript testing', + ' ,', + ']', + ].join('\n'), + ); + }); + + it('supports maxDepth option', () => { + const dt = document.createElement('dt'); + dt.innerHTML = 'jest'; + + const dd1 = document.createElement('dd'); + dd1.innerHTML = 'to talk in a playful manner'; + + const dd2 = document.createElement('dd'); + dd2.innerHTML = 'painless JavaScript testing'; + dd2.setAttribute('style', 'color: #99424F'); + + const dl = document.createElement('dl'); + dl.appendChild(dt); + dl.appendChild(dd1); + dl.appendChild(dd2); + + expect(dl).toPrettyPrintTo( + [ + '
', + '
', + ' jest', + '
', + '
', + ' to talk in a ', + ' ', + ' manner', // plugin incorrectly trims preceding space + '
', + ' ', + ' ', + ' JavaScript testing', // plugin incorrectly trims preceding space + ' ', + '
', + ].join('\n'), + {maxDepth: 2}, + ); + }); }); diff --git a/packages/pretty-format/src/plugins/html_element.js b/packages/pretty-format/src/plugins/html_element.js index 9ff149f20986..508275640d84 100644 --- a/packages/pretty-format/src/plugins/html_element.js +++ b/packages/pretty-format/src/plugins/html_element.js @@ -8,15 +8,10 @@ * @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'; +import {printElement, printElementAsLeaf, printProps} from './lib/markup'; type Attribute = { name: string, @@ -34,71 +29,52 @@ type HTMLText = { data: string, nodeType: 3, }; - type HTMLComment = { data: string, nodeType: 8, }; const HTML_ELEMENT_REGEXP = /(HTML\w*?Element)|Text|Comment/; -export const test = isHTMLElement; - -function isHTMLElement(value: any) { - return ( - value !== undefined && - value !== null && - (value.nodeType === 1 || value.nodeType === 3 || value.nodeType === 8) && - value.constructor !== undefined && - value.constructor.name !== undefined && - HTML_ELEMENT_REGEXP.test(value.constructor.name) - ); -} - -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); - } - }) - .filter(value => value.trim().length) - .join(opts.edgeSpacing); -} -function printAttributes( - attributes: Array, - print, - indent, - colors, - opts, -) { - return attributes - .sort( - (attributeA, attributeB) => - attributeA.name === attributeB.name - ? 0 - : attributeA.name < attributeB.name ? -1 : 1, +export const test = (val: any) => + val !== undefined && + val !== null && + (val.nodeType === 1 || val.nodeType === 3 || val.nodeType === 8) && + val.constructor !== undefined && + val.constructor.name !== undefined && + HTML_ELEMENT_REGEXP.test(val.constructor.name); + +// Return empty string if children is empty. +function printChildren(children, config, indentation, depth, refs, printer) { + const colors = config.colors; + return children + .map( + node => + typeof node === 'string' + ? colors.content.open + escapeHTML(node) + colors.content.close + : printer(node, config, indentation, depth, refs), ) - .map(attribute => { - return ( - opts.spacing + - indent(colors.prop.open + attribute.name + colors.prop.close + '=') + - colors.value.open + - print(attribute.value) + - colors.value.close - ); - }) + .filter(value => value.trim().length) + .map(value => config.spacingOuter + indentation + value) .join(''); } -export const print = ( +const getType = element => element.tagName.toLowerCase(); + +// Convert array of attribute objects to keys array and props object. +const keysMapper = attribute => attribute.name; +const propsReducer = (props, attribute) => { + props[attribute.name] = attribute.value; + return props; +}; + +export const serialize = ( element: HTMLElement | HTMLText | HTMLComment, - print: Print, - indent: Indent, - opts: PluginOptions, - colors: Colors, + config: Config, + indentation: string, + depth: number, + refs: Refs, + printer: Printer, ): string => { if (element.nodeType === 3) { return element.data @@ -106,7 +82,10 @@ export const print = ( .map(text => text.trimLeft()) .filter(text => text.length) .join(' '); - } else if (element.nodeType === 8) { + } + + const colors = config.colors; + if (element.nodeType === 8) { return ( colors.comment.open + '