diff --git a/CHANGELOG.md b/CHANGELOG.md
index 731eb7ca0a25..0da4c29b0788 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
- `[jest-config]` Add `readConfigs` function, previously in `jest-cli` ([#7096](https://github.com/facebook/jest/pull/7096))
- `[jest-snapshot]` Enable configurable snapshot paths ([#6143](https://github.com/facebook/jest/pull/6143))
- `[jest-haste-map]` [**BREAKING**] Remove support for `@providesModule` ([#6104](https://github.com/facebook/jest/pull/6104))
+- `[pretty-format]` Support HTMLCollection and NodeList in DOMCollection plugin ([#7125](https://github.com/facebook/jest/pull/7125))
### Fixes
diff --git a/packages/pretty-format/src/__tests__/dom_collection.test.js b/packages/pretty-format/src/__tests__/dom_collection.test.js
index 38128a3ff8c6..cf0d498f8b18 100644
--- a/packages/pretty-format/src/__tests__/dom_collection.test.js
+++ b/packages/pretty-format/src/__tests__/dom_collection.test.js
@@ -12,26 +12,150 @@
'use strict';
const prettyFormat = require('../');
-const {DOMCollection} = prettyFormat.plugins;
+const {DOMCollection, DOMElement} = prettyFormat.plugins;
const toPrettyPrintTo = require('./expect_util').getPrettyPrint([
DOMCollection,
+ DOMElement,
]);
const expect: any = global.expect;
expect.extend({toPrettyPrintTo});
-describe('DOMCollection Plugin', () => {
- it('supports a DOMStringMap', () => {
+describe('DOMCollection plugin for object properties', () => {
+ it('supports DOMStringMap', () => {
const el = document.createElement('div');
el.dataset.foo = 'bar';
expect(el.dataset).toPrettyPrintTo('DOMStringMap {\n "foo": "bar",\n}');
});
- it('supports a NamedNodeMap', () => {
+ it('supports NamedNodeMap', () => {
const el = document.createElement('div');
el.setAttribute('foo', 'bar');
expect(el.attributes).toPrettyPrintTo('NamedNodeMap {\n "foo": "bar",\n}');
});
+
+ it('supports config.min option', () => {
+ const el = document.createElement('div');
+ el.setAttribute('name1', 'value1');
+ el.setAttribute('name2', 'value2');
+
+ expect(el.attributes).toPrettyPrintTo(
+ '{"name1": "value1", "name2": "value2"}',
+ {min: true},
+ );
+ });
+});
+
+describe('DOMCollection plugin for list items', () => {
+ const select = document.createElement('select');
+ select.innerHTML = [
+ '',
+ '',
+ '',
+ ].join('');
+
+ const form = document.createElement('form');
+ form.appendChild(select);
+
+ const expectedOption1 = [
+ ' ,', // comma because item
+ ].join('\n');
+ const expectedOption2 = [
+ ' ,', // comma because item
+ ].join('\n');
+ const expectedOption3 = [
+ ' ,', // comma because item
+ ].join('\n');
+
+ const expectedHTMLCollection = [
+ 'HTMLCollection [',
+ expectedOption1,
+ expectedOption2,
+ expectedOption3,
+ ']',
+ ].join('\n');
+
+ it('supports HTMLCollection for getElementsByTagName', () => {
+ const options = form.getElementsByTagName('option');
+ expect(options).toPrettyPrintTo(expectedHTMLCollection);
+ });
+
+ it('supports HTMLCollection for children', () => {
+ expect(select.children).toPrettyPrintTo(expectedHTMLCollection);
+ });
+
+ it('supports config.maxDepth option', () => {
+ expect(select.children).toPrettyPrintTo('[HTMLCollection]', {maxDepth: 0});
+ });
+
+ const expectedNodeList = [
+ 'NodeList [',
+ expectedOption1,
+ expectedOption2,
+ expectedOption3,
+ ']',
+ ].join('\n');
+
+ it('supports NodeList for querySelectorAll', () => {
+ const options = form.querySelectorAll('option');
+ expect(options).toPrettyPrintTo(expectedNodeList);
+ });
+
+ it('supports NodeList for childNodes', () => {
+ expect(select.childNodes).toPrettyPrintTo(expectedNodeList);
+ });
+
+ const expectedHTMLOptionsCollection = [
+ 'HTMLOptionsCollection [',
+ expectedOption1,
+ expectedOption2,
+ expectedOption3,
+ ']',
+ ].join('\n');
+
+ it('supports HTMLOptionsCollection for select options', () => {
+ expect(select.options).toPrettyPrintTo(expectedHTMLOptionsCollection);
+ });
+
+ // When Jest upgrades to a version of jsdom later than 12.2.0,
+ // the class name might become HTMLFormControlsCollection
+ const expectedHTMLFormControlsCollection = [
+ 'HTMLCollection [',
+ ' ,', // comma because item
+ ']',
+ ].join('\n');
+
+ it('supports HTMLCollection for form elements', () => {
+ expect(form.elements).toPrettyPrintTo(expectedHTMLFormControlsCollection);
+ });
});
diff --git a/packages/pretty-format/src/plugins/dom_collection.js b/packages/pretty-format/src/plugins/dom_collection.js
index 5af357b05af5..716e83829617 100644
--- a/packages/pretty-format/src/plugins/dom_collection.js
+++ b/packages/pretty-format/src/plugins/dom_collection.js
@@ -9,29 +9,26 @@
import type {Config, NewPlugin, Printer, Refs} from 'types/PrettyFormat';
-import {printObjectProperties} from '../collections';
+import {printListItems, printObjectProperties} from '../collections';
const SPACE = ' ';
-const COLLECTION_NAMES = ['DOMStringMap', 'NamedNodeMap'];
+const OBJECT_NAMES = ['DOMStringMap', 'NamedNodeMap'];
+const ARRAY_REGEXP = /^(HTML\w*Collection|NodeList)$/;
+
+const testName = (name: any) =>
+ OBJECT_NAMES.indexOf(name) !== -1 || ARRAY_REGEXP.test(name);
export const test = (val: any) =>
val &&
val.constructor &&
- COLLECTION_NAMES.indexOf(val.constructor.name) !== -1;
-
-const convertCollectionToObject = (collection: any) => {
- let result = {};
-
- if (collection.constructor.name === 'NamedNodeMap') {
- for (let i = 0; i < collection.length; i++) {
- result[collection[i].name] = collection[i].value;
- }
- } else {
- result = Object.assign({}, collection);
- }
+ val.constructor.name &&
+ testName(val.constructor.name);
- return result;
+// Convert array of attribute objects to props object.
+const propsReducer = (props, attribute) => {
+ props[attribute.name] = attribute.value;
+ return props;
};
export const serialize = (
@@ -42,23 +39,36 @@ export const serialize = (
refs: Refs,
printer: Printer,
): string => {
+ const name = collection.constructor.name;
if (++depth > config.maxDepth) {
- return '[' + collection.constructor.name + ']';
+ return '[' + name + ']';
}
return (
- collection.constructor.name +
- SPACE +
- '{' +
- printObjectProperties(
- convertCollectionToObject(collection),
- config,
- indentation,
- depth,
- refs,
- printer,
- ) +
- '}'
+ (config.min ? '' : name + SPACE) +
+ (OBJECT_NAMES.indexOf(name) !== -1
+ ? '{' +
+ printObjectProperties(
+ name === 'NamedNodeMap'
+ ? Array.prototype.reduce.call(collection, propsReducer, {})
+ : Object.assign({}, collection),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer,
+ ) +
+ '}'
+ : '[' +
+ printListItems(
+ Array.from(collection),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer,
+ ) +
+ ']')
);
};