Skip to content

Conversation

mbelsky
Copy link
Contributor

@mbelsky mbelsky commented Oct 2, 2019

Hey,

I face an issue and come with this pr :)

What:

Add strict check for dom's outerHTML field

Why:

To improve DX.

As a new user I've called debug(x) where x was a result of queryAll*. I've missed that queryAll* returns an array and got TypeError: Cannot read property 'length' of undefined in my terminal.

Checklist:

maxLength = getMaxLength(dom),
options,
) {
if (!(dom instanceof HTMLDocument) && !(dom instanceof HTMLElement)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the error is thrown at dom.outerHTML.length which means Element is sufficient. Otherwise we would also throw on svg elements.

Do we need to consider cross-realm instanceof checks here as well? Getting the window of an element would not work if we didn't get an Element in the first place. I think checking for typeof dom.outerHTML === 'string' might be sufficient here in asserting that the given value implements Element.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose the error is thrown at dom.outerHTML.length which means Element is sufficient. Otherwise we would also throw on svg elements.

Unfortunately it isn't because document isn't an instance of Element

I think checking for typeof dom.outerHTML === 'string' might be sufficient here in asserting that the given value implements Element.

I absolutely agree that typeof dom.outerHTML === 'string' checking is enough however it may hide a real problem from a developer

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately it isn't because document isn't an instance of Element

Which is why you would keep the HTMLDocument check.

Cross-realm problem still exists.

I absolutely agree that typeof dom.outerHTML === 'string' checking is enough however it may hide a real problem from a developer

That would be?

IMO runtime type checking is not necessary here. If people care about type checking then you already have very good solutions with flow or typescript.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types may lies. Right now dom typed as HTMLElement

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/403ac51161e5773d0ec7eb965004e18e9d4a03c8/types/testing-library__dom/pretty-dom.d.ts#L3

However there is a test for rendering document

test('prettyDOM supports receiving the document element', () => {
expect(prettyDOM(document)).toMatchInlineSnapshot(`

Runtime checking isn't a silver bullet however it allows to fail fast when a library's user use it as not expected and teaches she how to do it right.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types may lies

Did it occur to you that it was a mistake instead of an intention to specify something wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it did.

For me as a developer it's so cool to have strict contracts in a library. What do you think about an alternative conditional here like:

- if (!(dom instanceof HTMLDocument) && !(dom instanceof HTMLElement)) {
-     throw new TypeError(
-      'Debuggable value should be an instance of HTMLDocument or HTMLElement.',
-    )
- }
+ if (!('outerHTML' in dom)) {
+     throw new TypeError(
+      'Debuggable object should have `outerHTML` field like an HTMLElement instance.',
+    )
+ }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds better but you're still using HTMLElement which is too narrow. No need throw so many technicallaties around "Expected an element or document but got X".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for suggestion. I've updated this check and add a test

@mbelsky
Copy link
Contributor Author

mbelsky commented Oct 7, 2019

I didn't extend pretty-dom.js functional and cover added condition with a test. However ci fails with:

Jest: "global" coverage threshold for branches (100%) not met: 99.59%
...
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @testing-library/dom@0.0.0-semantically-released validate: `kcd-scripts validate`
npm ERR! Exit status 1
npm ERR! 

Does it mean that I should write some tests for pretty-dom.js?

}
if (!('outerHTML' in dom)) {
const domType = typeof dom
const domTypeName = domType === 'object' ? dom.constructor.name : domType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch is likely not covered. Also: This will throw on null because typeof null === 'object'.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. Thank you for explaining.

dom = getDocument().body,
maxLength = getMaxLength(dom),
options,
) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inCypress has failed with null parameter so in addition I replaced arguments default initializations.

Copy link
Member

@kentcdodds kentcdodds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me 👍

@kentcdodds kentcdodds merged commit 99760f0 into testing-library:master Oct 7, 2019
@kentcdodds
Copy link
Member

@all-contributors please add @mbelsky for code and tests

@allcontributors
Copy link
Contributor

@kentcdodds

I've put up a pull request to add @mbelsky! 🎉

@kentcdodds
Copy link
Member

🎉 This PR is included in version 6.6.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants