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
Add docs about decision around, and alternatives to, testID #35
Conversation
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.
looks great. Should we also mention the issue of tracking (trekkie, etc.) that seemingly prompted us to move away from testIDs?
it('includes the children in the markup', () => { | ||
const children = <div>Contents</div>; | ||
const card = mount(<Card>{children}</Card>); | ||
expect(card).toContainReact(children); |
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.
TIL ❤️
|
||
To make this approach even easier, our [`enzyme-utilities` package](https://github.com/Shopify/quilt/tree/master/packages/enzyme-utilities) provides a `findById` utility function. | ||
|
||
* If neither of the above apply, filter the set of matched components based on the properties that are unique to them. If no properties are unique, fall back to the index of the item in the matched set. |
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 wording is a bit confusing to me. To confirm, if you can't make it into a separate component, and a unique ID doesn't make sense, then simply find all instances of the component and filter them by some other unique thing like text or a prop. If there are no unique attributes that make sense, then locate the item by its index (ex. the second modal)?
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, that is exactly correct (text is always a prop of the component, but I wanted to try to not tie this entire section just to React)
@@ -0,0 +1,49 @@ | |||
# We do not use test IDs in tests |
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.
maybe just We do not use test IDs
?
We ran into this problem with our I think that removing The proposed changes make sense 👍 but we will definitely have to do some refactoring in multiple places to respect this new best practice. |
it('includes the children in the markup', () => { | ||
const children = <div>Contents</div>; | ||
const card = mount(<Card>{children}</Card>); | ||
expect(card).toContainReact(children); |
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.
Really nice, didn't know you could do that.
Love it! Simple yet in-depth explanation of a really important practice. |
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.
👏
Best practices/Testing.md
Outdated
* Markup that has an important effect on the visual output of a component, but which have no other defining characteristics (for example, an element on which we apply a particular class name or inline styles). | ||
* A child component that is rendered multiple times, where the developer wishes to easily disambiguate between the instances (for example, a component that renders multiple `Modal`s from Polaris React). | ||
|
||
We would like to avoid test IDs for handling the cases above, as make it easy to reach into your component in ways that unnecessarily lock down the implementation. You can typically avoid test IDs by using one of the following strategies: |
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.
as make it easy
=> as they make it easy
|
||
## Description | ||
|
||
Developers sometimes feel the need to add "hooks" that allow their tests to easily find parts of the component subtree and assert details about those subtrees in tests. In the React ecosystem, this is a key recommendation of an alternative to Enzyme (our preferred React testing library), [`react-testing-library`/ `dom-testing-library`](https://github.com/kentcdodds/dom-testing-library/blob/master/README.md#faq). |
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 second sentence is distracting and does not really add anything.
In building the initial version of Shopify Web, we took several steps to encourage and facilitate the use of test IDs: | ||
|
||
* A [babel plugin](https://github.com/lemonmade/babel-plugin-react-test-id) to remove the unnecessary attribute in production | ||
* Allowing the `testID` prop implicitly with TypeScript and adding a `findByTestId` utility to Shopify Web |
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 2 separate bullets, but its fine.
* A [babel plugin](https://github.com/lemonmade/babel-plugin-react-test-id) to remove the unnecessary attribute in production | ||
* Allowing the `testID` prop implicitly with TypeScript and adding a `findByTestId` utility to Shopify Web | ||
|
||
These were originally introduced to facilitate differentiation between the same React component rendered multiple times within a tree (specifically, to target multiple `TextField` components rendered by a card in the product section of the admin). No analysis of alternatives was performed at the time. The cases in which this attribute was used expanded and, as of July 10, 2018, it is used 280 times in the Web codebase. |
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 don't think you need the part in parens. And maybe Web
should be Shopify Web
to match when it is mentioned above.
|
||
## Decision | ||
|
||
`testID` provides some benefits that have made it attractive to developers working in the Web stack: |
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.
Web
=> Shopify Web
* You must prevent console warnings that React prints by default complaining about an unexpected `testID` prop on DOM elements | ||
* You must be sure to include our custom Babel plugin to strip the attribute in production builds | ||
|
||
Additionally, in reviewing the use of `testID` in Web, we found that the ways it were used were better addressed using other strategies. We have detailed common patterns we found (along with alternative strategies to `testID`) in our [testing best practices](../Best%20practices/Testing.md#test-ids), but in summary, we found that `testID` was used to: |
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.
Web
=> Shopify Web
(or change them all to just Web
). I don't have a preference other than that it is consistent.
Update changelog for release 5.1.0
Use full module name for presets
Does what it says on the tin. I wanted to get this down into words so people understand why we are mostly opposed to the use of this attribute, provide some historical context for why we have so many in the existing Web app, and give people alternatives for the common patterns I have seen.
cc/ @Shopify/web-foundation