Skip to content

Commit

Permalink
Support text and comment nodes in html pretty printing (jestjs#3355)
Browse files Browse the repository at this point in the history
* Make sure pretty-format expect util has correct context

* Support comment nodes in html pretty printing

* Support text nodes in html pretty printing

* Add comment key to pretty-format theme

* Add type to element in html pretty printer

* Remove unused arg from html pretty printer

* Cleanup
  • Loading branch information
SimenB authored and cpojer committed Apr 28, 2017
1 parent 345f0ed commit cc92f5e
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 50 deletions.
54 changes: 48 additions & 6 deletions packages/pretty-format/src/__tests__/HTMLElementPlugin-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @jest-environment jsdom
*/
/* eslint-disable max-len */
/* eslint-env browser*/

'use strict';
Expand Down Expand Up @@ -50,10 +49,7 @@ describe('HTMLElement Plugin', () => {
parent.setAttribute('id', 123);
parent.setAttribute('class', 'classy');

expect(parent).toPrettyPrintTo(
'<div\n id="123"\n class="classy"\n/>',
{},
);
expect(parent).toPrettyPrintTo('<div\n id="123"\n class="classy"\n/>');
});

it('supports an element with text content', () => {
Expand Down Expand Up @@ -93,4 +89,50 @@ describe('HTMLElement Plugin', () => {
'<div>\n <span>\n texty texty\n </span>\n</div>',
);
});

it('supports siblings', () => {
const parent = document.createElement('div');
parent.innerHTML = '<span>some </span><span>text</span>';

expect(parent).toPrettyPrintTo(
[
'<div>',
' <span>',
' some ',
' </span>',
' <span>',
' text',
' </span>',
'</div>',
].join('\n'),
);
});

it('supports text node', () => {
const parent = document.createElement('div');
parent.innerHTML = 'some <span>text</span>';

// prettier-ignore
expect(parent).toPrettyPrintTo([
'<div>',
' some ',
' <span>',
' text',
' </span>',
'</div>',
].join('\n'));
});

it('supports comment node', () => {
const parent = document.createElement('div');
parent.innerHTML = 'some <!-- comments -->';

// prettier-ignore
expect(parent).toPrettyPrintTo([
'<div>',
' some ',
' <!-- comments -->',
'</div>',
].join('\n'));
});
});
67 changes: 34 additions & 33 deletions packages/pretty-format/src/__tests__/expect-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/

'use strict';
Expand All @@ -13,41 +13,42 @@ const diff = require('jest-diff');
const prettyFormat = require('../');

module.exports = {
getPrettyPrint: plugins => (received, expected, opts) => {
const prettyFormatted = prettyFormat(
received,
Object.assign(
{
plugins,
},
opts,
),
);
const pass = prettyFormatted === expected;
getPrettyPrint: plugins =>
function(received, expected, opts) {
const prettyFormatted = prettyFormat(
received,
Object.assign(
{
plugins,
},
opts,
),
);
const pass = prettyFormatted === expected;

const message = pass
? () =>
this.utils.matcherHint('.not.toBe') +
'\n\n' +
`Expected value to not be:\n` +
` ${this.utils.printExpected(expected)}\n` +
`Received:\n` +
` ${this.utils.printReceived(prettyFormatted)}`
: () => {
const diffString = diff(expected, prettyFormatted, {
expand: this.expand,
});
return (
this.utils.matcherHint('.toBe') +
const message = pass
? () =>
this.utils.matcherHint('.not.toBe') +
'\n\n' +
`Expected value to be:\n` +
`Expected value to not be:\n` +
` ${this.utils.printExpected(expected)}\n` +
`Received:\n` +
` ${this.utils.printReceived(prettyFormatted)}` +
(diffString ? `\n\nDifference:\n\n${diffString}` : '')
);
};
` ${this.utils.printReceived(prettyFormatted)}`
: () => {
const diffString = diff(expected, prettyFormatted, {
expand: this.expand,
});
return (
this.utils.matcherHint('.toBe') +
'\n\n' +
`Expected value to be:\n` +
` ${this.utils.printExpected(expected)}\n` +
`Received:\n` +
` ${this.utils.printReceived(prettyFormatted)}` +
(diffString ? `\n\nDifference:\n\n${diffString}` : '')
);
};

return {actual: prettyFormatted, message, pass};
},
return {actual: prettyFormatted, message, pass};
},
};
12 changes: 9 additions & 3 deletions packages/pretty-format/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
const style = require('ansi-styles');

type Theme = {|
comment?: string,
content?: string,
prop?: string,
tag?: string,
Expand Down Expand Up @@ -799,6 +800,7 @@ const DEFAULTS: Options = {
printFunctionName: true,
spacing: '\n',
theme: {
comment: 'gray',
content: 'reset',
prop: 'yellow',
tag: 'cyan',
Expand Down Expand Up @@ -873,7 +875,13 @@ function prettyFormat(val: any, initialOptions?: InitialOptions): string {
opts = normalizeOptions(initialOptions);
}

const colors: Colors = {};
const colors: Colors = {
comment: {close: '', open: ''},
content: {close: '', open: ''},
prop: {close: '', open: ''},
tag: {close: '', open: ''},
value: {close: '', open: ''},
};
Object.keys(opts.theme).forEach(key => {
if (opts.highlight) {
const color = (colors[key] = style[opts.theme[key]]);
Expand All @@ -886,8 +894,6 @@ function prettyFormat(val: any, initialOptions?: InitialOptions): string {
`pretty-format: Option "theme" has a key "${key}" whose value "${opts.theme[key]}" is undefined in ansi-styles.`,
);
}
} else {
colors[key] = {close: '', open: ''};
}
});

Expand Down
44 changes: 37 additions & 7 deletions packages/pretty-format/src/plugins/HTMLElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,36 @@
import type {Colors, Indent, Options, Print, Plugin} from 'types/PrettyFormat';

const escapeHTML = require('./lib/escapeHTML');
const HTML_ELEMENT_REGEXP = /(HTML\w*?Element)/;

type Attribute = {
name: string,
value: string,
};

type HTMLElement = {
attributes: Array<Attribute>,
childNodes: Array<HTMLElement | HTMLText | HTMLComment>,
nodeType: 1,
tagName: string,
};
type HTMLText = {
data: string,
nodeType: 3,
};

type HTMLComment = {
data: string,
nodeType: 8,
};

const HTML_ELEMENT_REGEXP = /(HTML\w*?Element)|Text|Comment/;
const test = isHTMLElement;

function isHTMLElement(value: any) {
return (
value !== undefined &&
value !== null &&
value.nodeType === 1 &&
(value.nodeType === 1 || value.nodeType === 3 || value.nodeType === 8) &&
value.constructor !== undefined &&
value.constructor.name !== undefined &&
HTML_ELEMENT_REGEXP.test(value.constructor.name)
Expand All @@ -41,7 +63,7 @@ function printChildren(flatChildren, print, indent, colors, opts) {
.join(opts.edgeSpacing);
}

function printAttributes(attributes, print, indent, colors, opts) {
function printAttributes(attributes: Array<Attribute>, indent, colors, opts) {
return attributes
.sort()
.map(attribute => {
Expand All @@ -57,23 +79,31 @@ function printAttributes(attributes, print, indent, colors, opts) {
}

const print = (
element: any,
element: HTMLElement | HTMLText | HTMLComment,
print: Print,
indent: Indent,
opts: Options,
colors: Colors,
) => {
): string => {
if (element.nodeType === 3) {
return element.data;
} else if (element.nodeType === 8) {
return (
colors.comment.open + '<!--' + element.data + '-->' + colors.comment.close
);
}

let result = colors.tag.open + '<';
const elementName = element.tagName.toLowerCase();
result += elementName + colors.tag.close;

const hasAttributes = element.attributes && element.attributes.length;
if (hasAttributes) {
const attributes = Array.prototype.slice.call(element.attributes);
result += printAttributes(attributes, print, indent, colors, opts);
result += printAttributes(attributes, indent, colors, opts);
}

const flatChildren = Array.prototype.slice.call(element.children);
const flatChildren = Array.prototype.slice.call(element.childNodes);
if (!flatChildren.length && element.textContent) {
flatChildren.push(element.textContent);
}
Expand Down
9 changes: 8 additions & 1 deletion types/PrettyFormat.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
*/
'use strict';

export type Colors = Object;
export type Colors = {
comment: {close: string, open: string},
content: {close: string, open: string},
prop: {close: string, open: string},
tag: {close: string, open: string},
value: {close: string, open: string},
};
export type Indent = string => string;
export type Refs = Array<any>;
export type Print = any => string;
Expand All @@ -27,6 +33,7 @@ export type Options = {|
printFunctionName: boolean,
spacing: string,
theme: {|
comment: string,
content: string,
prop: string,
tag: string,
Expand Down

0 comments on commit cc92f5e

Please sign in to comment.