Skip to content
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

fix: Ignore comment nodes in toBeEmptyDOMElement #317

Merged
merged 8 commits into from Jan 12, 2021

Conversation

marcelbarner
Copy link
Contributor

@marcelbarner marcelbarner commented Dec 17, 2020

What:
Adding a logic to the existing toBeEmptyDOMElement to ignore comments in the element.

Why:
In some frameworks, like Angular, there is a logic to create elements on specific conditions. If this condition is not solved than the framework also adds some comments, this comment has the effect that the matcher toBeEmptyDOMElement fails, but the element is empty from the perspective of the user.

How:
The matcher checks if the element contains child elements excluded comment nodes.

Checklist:

  • Documentation
  • Tests
  • Updated Type Definitions
  • Ready to be merged

Adding a new matcher to check if a element only contains comments and no other elements or text.
@codecov
Copy link

codecov bot commented Dec 17, 2020

Codecov Report

Merging #317 (559bc43) into master (f930668) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #317   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           23        23           
  Lines          534       537    +3     
  Branches       197       197           
=========================================
+ Hits           534       537    +3     
Impacted Files Coverage Δ
src/to-be-empty-dom-element.js 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f930668...559bc43. Read the comment docs.

@nickmccurdy
Copy link
Member

It sounds like a good idea to support comments, but I think it would be easier to just patch toBeEmpty. I don't think there needs to be a distinction between empty elements and elements with only comments, as either way the element has no visible content.

@marcelbarner
Copy link
Contributor Author

It sounds like a good idea to support comments, but I think it would be easier to just patch toBeEmpty. I don't think there needs to be a distinction between empty elements and elements with only comments, as either way the element has no visible content.

I am agreed with your point, but than it is not a empty element. An alternative solution will be to combine both logics to a new matcher with the name toContainNoVisibleContent or something similar.

@nickmccurdy
Copy link
Member

It may not technically be empty, but practically speaking there's nothing that would be displayed to the user, and it's better for tests to represent the user's perspective than implementation details.

@marcelbarner
Copy link
Contributor Author

If we look from the user perspective, than I completely agree with your points. I will make the required adjustments.

After a small discussion move logic from custom matcher to the existing toBeEmptyDOMElement.
@marcelbarner marcelbarner changed the title feat: Add toContainOnlyComments matcher feat: Add ignoring comments in toBeEmptyDOMElement Dec 17, 2020
@marcelbarner
Copy link
Contributor Author

@nickmccurdy should I also add this logic to the matcher toBeEmpty? This matcher is marked as deprecated.
Also I have the problem to write a good test to validate that multiline comments are ignored. Can you maybe help me?

Copy link
Member

@gnapse gnapse left a comment

Choose a reason for hiding this comment

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

I had some questions about the regex being used, but then it hit me that I have objections with using regex in the first place. It will most likely be error prone to use a regex approach for this purpose.

I'd suggest we can use the DOM structure itself, instead of parsing anything ourselves. We can traverse the list of nodes inside the target element, and check if it has any child nodes that are not comments.

Here's a snippet that may serve as inspiration:

const nonCommentChildNodes = [...element.childNodes].filter(
    node => node.nodeType !== Node.COMMENT_NODE
)

If this list turns out empty, the target element is empty, and vice-versa.

Would love your thoughts on this one.

@gnapse
Copy link
Member

gnapse commented Dec 18, 2020

About this

should I also add this logic to the matcher toBeEmpty? This matcher is marked as deprecated.

I would not bother adding this fix to the deprecated matcher.

Also I have the problem to write a good test to validate that multiline comments are ignored. Can you maybe help me?

Using the DOM structure instead of parsing it ourselves will solve this.

@marcelbarner
Copy link
Contributor Author

I had some questions about the regex being used, but then it hit me that I have objections with using regex in the first place. It will most likely be error prone to use a regex approach for this purpose.

I'd suggest we can use the DOM structure itself, instead of parsing anything ourselves. We can traverse the list of nodes inside the target element, and check if it has any child nodes that are not comments.

Here's a snippet that may serve as inspiration:

const nonCommentChildNodes = [...element.childNodes].filter(
    node => node.nodeType !== Node.COMMENT_NODE
)

If this list turns out empty, the target element is empty, and vice-versa.

Would love your thoughts on this one.

I think this idea is the better solution to use the DOM structure with that the code will be more stable. I had some concerns about node elements which only contain whitespaces or text, but I tried it and seems to work. I will adjust my implementation.

Thanks for your nice catch.

@nickmccurdy
Copy link
Member

My mistake, I forgot about the deprecation, I meant toBeEmptyDOMElement.

@marcelbarner
Copy link
Contributor Author

No problem I am thank full for all of your great input, so thanks to you all.

@marcelbarner
Copy link
Contributor Author

Now I need your help again, because I am not an expert for jsdom.
If I use this this snipped to identify that an node element is a COMMENT_NODE

const nonCommentChildNodes = [...element.childNodes].filter(node => node.nodeType !== Node.COMMENT_NODE);

I get the following error:

  • ReferenceError: Node is not defined

After a research I found the following issue. I can not exactly identify what i have to do. I figured out that a workaround is to replace Node.COMMENT_NODE with 8 will work but I am not happy with a magic number or to redefine a global definition. So maybe you have an idea what i can do?

@gnapse
Copy link
Member

gnapse commented Dec 21, 2020

I suggest you declare a constant of our own and add a jsdoc comment to it explaining why we can't use Node.COMMENT_NODE (including a link to that github issue).

@nickmccurdy
Copy link
Member

Aren't we targeting the JSDOM environment of Jest which includes these values in the V8 context? They're not really globals, but any code in Jest DOM should be able to pretend they're globals as far as I understand.

Copy link
Member

@gnapse gnapse left a comment

Choose a reason for hiding this comment

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

Looking good. Requesting changes because of a few relatively minor observations. Let me know what you think.

README.md Outdated Show resolved Hide resolved
src/__tests__/to-be-empty-dom-element.js Outdated Show resolved Hide resolved
src/to-be-empty-dom-element.js Outdated Show resolved Hide resolved
src/to-be-empty-dom-element.js Outdated Show resolved Hide resolved
@gnapse gnapse changed the title feat: Add ignoring comments in toBeEmptyDOMElement fix: Ignore comment nodes in toBeEmptyDOMElement Jan 12, 2021
@marcelbarner marcelbarner reopened this Jan 12, 2021
@gnapse gnapse merged commit 6a6531d into testing-library:master Jan 12, 2021
@gnapse
Copy link
Member

gnapse commented Jan 12, 2021

@all-contributors please add @marcelbarner for code and test

@allcontributors
Copy link
Contributor

@gnapse

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

@github-actions
Copy link

🎉 This PR is included in version 5.11.9 🎉

The release is available on:

Your semantic-release bot 📦🚀

@gnapse
Copy link
Member

gnapse commented Feb 9, 2021

@all-contributors please add @marcelbarner for code and test

@allcontributors
Copy link
Contributor

@gnapse

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

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.

None yet

3 participants