-
Notifications
You must be signed in to change notification settings - Fork 205
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
Feat: prototype unit testing #712
Conversation
bumped @testing-library/react
add script to package.json
Deploy preview for stoplight-elements ready! Built with commit 0f43b92 |
added @testing-library/dom added @testing-library/user-event added a test case
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.
The setup is nice, it works great!
I'm not so much a fan of the tests however. I know they are just some examples, but they are not really good examples right now IMO. Let's tidy them up together!
As they stand now, both the selectors and the assertions use a lot of artificial artifacts such as the copy, data-*
attributes or test ids. These should be used as the last resort and when you use them you should question whether the thing is worth testing in the first place. We should always keep testing goals & pain/reward ratios in mind.
I offered you some tips on how I would make that one test nicer, but you can apply the same principles to most of the other selectors and assertions, too.
But it really is very difficult to come up with a good testing approach in regards to this component. And as I said, when encountering this, one should stop and rethink. So digging further down I think I found what the real problem is here: The component you picked doesn't have much behavior to test. If you open its source code you can see that's its completely static, does nothing - except for that popup that may very well be the only valid thing to test here. It's almost static HTML.
I don't think these static components are worth testing at all, because what can you assert? That it renders what's written into the source code? That doesn't offer any added value, does it? I think in general we are looking to test behavior and very little presentation, so maybe it all only has to do with the component choice. That's one of the reasons I suggested to do an overall test of API.
Having said that, if you can clean this one up - even if you only keep a single test - that's perfectly good enough as well to complete the connected issue. The issue says you can test anything, what I would not like however, is to merge an example of doing the wrong thing. Having a single very simple but nicely written example is much much better.
.circleci/config.yml
Outdated
@@ -17,6 +17,7 @@ jobs: | |||
- run: yarn --frozen-lockfile | |||
- run: yarn type-check | |||
- run: yarn lint | |||
- run: yarn test.clear |
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 do we need this?
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 related to kulshekhar/ts-jest#1506 - I encountered an error when trying to run tests with jest
a couple of times and clearing cache helped. We could get rid of for now and see if it breaks in CircleCI frequently, but it only adds about 2 seconds to a job.
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.
It cannot affect CircleCI because it's a new container each time, with an empty cache - that's also why it takes 2s.
This justifies having the yarn
command however, if it is useful for you locally.
The issue you linked to is closed however ("v26.1.4 is out, I will close this issue"), so you could try upgrading ts-jest
(by upgrading jest
itself) and that should fix your local problems as well.
expect(elem.innerHTML).toContain('data-icon="magic"'); | ||
expect(elem.innerHTML).toContain('data-icon="question-circle"'); |
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 implementation-dependent and unimportant
await screen.findByText( | ||
"Send HTTP requests to your API, or one of our mock servers, to see how it's going to respond. View the docs", | ||
), |
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.
Testing the copy is rarely a good idea either. The only thing it does is makes it more annoying to change it down the road, without providing any real safety.
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.
But testing whether the popover works is a good one!
Now on how to select it? One really underrated and underutilized way of selecting things is by accessibility attributes (ARIA).
You may be familiar already that HTML5 includes many new "semantic" tags that behave the same as a regular div
, but mean a slightly different thing. section
, main
, article
, etc. Since HTML5, the official goal of HTML is to describe semantics, not to prescribe appearance or behavior. (We have CSS and JS for those, respectively.) We should utilize this semantic part of HTML more than we do right now, but that's another matter.
In addition to these, a more in-depth way to describe a web-page is using the HTML accessibility attributes: https://www.w3.org/TR/wai-aria-1.1/ & https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics
While these are mainly designed to provide accessibility to websites - help screen readers and such - they implicitly let you describe the semantics of your site really well, the very semantics that you want to test. I tend to think of these as tools aiding testability and comprehension, and think of the accessibility improvement as a nice side-effect.
In this case using the tooltip role would be a perfect fit, then you could use the screen.findByRole
selector to find the element and instead of asserting on the contents you could assert e.g. toBeVisible
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.
Testing the copy is rarely a good idea either. The only thing it does is makes it more annoying to change it down the road, without providing any real safety.
I agree and will get rid of it
I agree, let's drop the checking of displayed text
I wanted to test that as well, but ran into a situation when |
Understood. 👍 Then let's just narrow this down to as much as we can, I'm fine with only having that single test that asserts that the tooltip is visible on hover. I don't think there's any more behavior in this component at all, but if you think so, sure, let's add that, too. |
@marcelltoth bear in mind that there's still a need to add a |
I guess it's fine for now. It's an example afterall, we won't be testing Popups like this much anymore |
removed unused data-testid attribute
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.
The test looks quite pretty and concise now, I love it! 🎉
You could remove all the --clearCache
-related lines, they shouldn't be needed anymore. If someone really wants to run it they can always run yarn test --clearCache
or yarn jest --clearCache
or yarn workspace run jest --clearCache
if you want to run it everywhere. We shouldn't create yarn commands for everything we might need to do, only the most frequent.
Other than that, good to go! 🚀
Closes: #660
react-testing-library
and its utilitiesjest
config file to handlenode modules
mappingsdata-testid
attributesTry It Out
header componentjest
cache beforehand (due to recurring errors in loading test files; solution: ts-jest 26.1.2 - "cannot find source file" kulshekhar/ts-jest#1506)