diff --git a/CHANGELOG.md b/CHANGELOG.md
index e54f28c38b77..e2c3d6f74533 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
- `[jest-changed-files]` Use `git diff` instead of `git log` for `--changedSince` ([#10155](https://github.com/facebook/jest/pull/10155))
- `[jest-console]` Add missing console.timeLog for compatability with Node ([#10209](https://github.com/facebook/jest/pull/10209))
- `[jest-snapshot]` Strip added indentation for inline error snapshots ([#10217](https://github.com/facebook/jest/pull/10217))
+- `[pretty-print]` Added support for serializing custom elements (web components) ([#10217](https://github.com/facebook/jest/pull/10237))
### Chore & Maintenance
diff --git a/packages/pretty-format/src/__tests__/DOMElement.test.ts b/packages/pretty-format/src/__tests__/DOMElement.test.ts
index b5e22f549c40..3faf79a7aa82 100644
--- a/packages/pretty-format/src/__tests__/DOMElement.test.ts
+++ b/packages/pretty-format/src/__tests__/DOMElement.test.ts
@@ -344,6 +344,29 @@ Testing.`;
);
});
+ it('supports custom elements', () => {
+ class CustomElement extends HTMLElement {}
+ class CustomExtendedElement extends CustomElement {}
+
+ customElements.define('custom-element', CustomElement);
+ customElements.define('custom-extended-element', CustomExtendedElement);
+
+ const parent = document.createElement('div');
+ parent.innerHTML = [
+ '',
+ '',
+ ].join('');
+
+ expect(parent).toPrettyPrintTo(
+ [
+ '
',
+ ' ',
+ ' ',
+ '
',
+ ].join('\n'),
+ );
+ });
+
describe('matches constructor name of SVG elements', () => {
// Too bad, so sad, element.constructor.name of SVG elements
// is HTMLUnknownElement in jsdom v9 and v10
diff --git a/packages/pretty-format/src/plugins/DOMElement.ts b/packages/pretty-format/src/plugins/DOMElement.ts
index daf8f9be721f..a40353e2ca63 100644
--- a/packages/pretty-format/src/plugins/DOMElement.ts
+++ b/packages/pretty-format/src/plugins/DOMElement.ts
@@ -23,17 +23,21 @@ const FRAGMENT_NODE = 11;
const ELEMENT_REGEXP = /^((HTML|SVG)\w*)?Element$/;
-const testNode = (nodeType: number, name: string) =>
- (nodeType === ELEMENT_NODE && ELEMENT_REGEXP.test(name)) ||
- (nodeType === TEXT_NODE && name === 'Text') ||
- (nodeType === COMMENT_NODE && name === 'Comment') ||
- (nodeType === FRAGMENT_NODE && name === 'DocumentFragment');
+const testNode = (val: any) => {
+ const constructorName = val.constructor.name;
+ const {nodeType, tagName = ''} = val;
+
+ return (
+ (nodeType === ELEMENT_NODE &&
+ (ELEMENT_REGEXP.test(constructorName) || tagName.indexOf('-') !== -1)) ||
+ (nodeType === TEXT_NODE && constructorName === 'Text') ||
+ (nodeType === COMMENT_NODE && constructorName === 'Comment') ||
+ (nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment')
+ );
+};
export const test: NewPlugin['test'] = (val: any) =>
- val &&
- val.constructor &&
- val.constructor.name &&
- testNode(val.nodeType, val.constructor.name);
+ val && val.constructor && val.constructor.name && testNode(val);
type HandledType = Element | Text | Comment | DocumentFragment;