-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds HtmlElement pretty-format plugin. #3230
Conversation
Merging changes from Origin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! Left some comments inlined. Btw, that's great usage of @jest-environment
pragma 👍
module.exports = { | ||
getPrettyPrint: plugins => | ||
(received, expected, opts) => { | ||
const prettyPrintImmutable = prettyFormat( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use some generic naming here, e.g. prettyPrintPlugin
opts, | ||
), | ||
); | ||
const pass = prettyPrintImmutable === expected; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
|
||
const escapeHTML = require('./lib/escapeHTML'); | ||
const HTML_ELEMENT_REGEXP = /(HTML\w*?Element)/; | ||
const test = (maybeSet: any) => isHTMLElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change naming, it's not Set
val.constructor && | ||
val.constructor.name && | ||
HTML_ELEMENT_REGEXP.test(val.constructor.name)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is potentially a hot place, please keep perf in mind: https://twitter.com/bmeurer/status/846951275480711168
describe('HTMLElement Plugin', () => { | ||
it('supports a single HTML element', () => { | ||
expect(document.createElement('div')).toPrettyPrintTo( | ||
'<HTMLDivElement />', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why double space?
const child = document.createElement('span'); | ||
parent.appendChild(child); | ||
expect(parent).toPrettyPrintTo( | ||
'<HTMLDivElement >\n <HTMLSpanElement />\n</HTMLDivElement >', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this extra space also here: <HTMLDivElement >
child.setAttribute('class', 'classy'); | ||
|
||
expect(parent).toPrettyPrintTo( | ||
'<HTMLDivElement >\n <HTMLSpanElement \n id=123\n class=classy\n />\n</HTMLDivElement >', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attributes should be strings id="123" class="classy"
.
Reworks short circuiting logic for `isHTMLElement` function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
const test = isHTMLElement; | ||
|
||
function isHTMLElement(value: any) { | ||
const toStringed = value.toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit worried about performance here. This will call toString on any value passed to pretty-format. toString may be expensive if it is overwritten on a class instance. Can we do Object.prototype.toString.call
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a really good call -- I'll check how that behaves on an actual JSDOM HTMLElement to verify.
Looking at it again, I think it's possible that we could just remove this toString
completely and just rely on the constructor validation, but I was deferring to the existing implementation from the previous PR.
Does that seem reasonable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I think we could make it even more performant. According to ElementImpl we could check for property nodeType
. Although this prop alone could possibly result in some false positives (nodeType
feels not so unique...), it's good for an early check. Only when we know there's such prop, we could perform constructor and regex check:
const test = (value: any) =>
value !== undefined &&
value.nodeType === 1 &&
value.constructor !== undefined &&
HTML_ELEMENT_REGEXP.test(value.constructor.name);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome -- I've updated the PR with those changes.
I'm not sure what to do about the tests that are failing; do I need to have mercurial configured locally for those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as stated here, point 6: https://github.com/facebook/jest/blob/master/CONTRIBUTING.md#workflow-and-pull-requests
const toPrettyPrintTo = require('./expect-util').getPrettyPrint([ | ||
ReactElementPlugin, | ||
ReactTestComponentPlugin, | ||
...ImmutablePlugins, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Node 4 fails because of this destructuring. You can use concat
instead
Codecov Report
@@ Coverage Diff @@
## master #3230 +/- ##
==========================================
+ Coverage 64.24% 64.41% +0.16%
==========================================
Files 175 176 +1
Lines 6436 6469 +33
Branches 4 4
==========================================
+ Hits 4135 4167 +32
- Misses 2300 2301 +1
Partials 1 1
Continue to review full report at Codecov.
|
|
Sure thing! |
@@ -60,7 +61,7 @@ const print = ( | |||
) => { | |||
let result = colors.tag.open + '<'; | |||
const elementName = element.constructor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const elementName = element.tagName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tagName
defaults to all uppercase, which felt odd to me -- should I leave it that way or is the .toLowerCase()
call okay here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lower case is better, leave it as is :)
Thanks for doing this! |
* Adds HtmlElement pretty-format plugin. * Adds missing copyright and 'use strict' * Fixes variable naming / formatting. Reworks short circuiting logic for `isHTMLElement` function. * Improves performance for isHtmlElement. * Updating snapshots * Revert "Updating snapshots" This reverts commit 55f797f. * Fixes node 4 syntax * - Switches to tagName rather than constructor. * Adds HTMLElement Plugin usage. * Removes `HTMLElement` fallback in favor of tagName
* Adds HtmlElement pretty-format plugin. * Adds missing copyright and 'use strict' * Fixes variable naming / formatting. Reworks short circuiting logic for `isHTMLElement` function. * Improves performance for isHtmlElement. * Updating snapshots * Revert "Updating snapshots" This reverts commit 55f797f. * Fixes node 4 syntax * - Switches to tagName rather than constructor. * Adds HTMLElement Plugin usage. * Removes `HTMLElement` fallback in favor of tagName
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
This addresses the issue noted in #2146, with
jsdom
HTMLElement's producing an absurdly long string when pretty formatted. It adds anHTMLElement
plugin which can be used to appropriatelypretty-format
these elements.Test plan
I tested this using a variety of unit tests, similar to the existing tests that were covering
ReactElement
.The cases I covered were ensuring that the class / title properties would pretty-format correctly, along with attributes on single elements and nested elements.
Here is the output from running those tests: