-
Notifications
You must be signed in to change notification settings - Fork 273
Reorganize internal queries code by predicate typ #325
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
Comments
Good call, let's do it.
This is an implementation detail. I guess that in some far-away future some optimizations may be added, but it's not the case now, and I don't think it has any priority. Once RTR does that, we can think about including these optimizations. |
I'd be glad to lend a hand on this issue @thymikee @mdjastrzebski. I could try to do it for one query before validating with you, what do you think? |
@MattAgn lovely! |
It looks like the PRs above have changed the results of the API. Before these changes the try {
return instance.find((node) => getNodeByText(node, text));
} catch (error) {
throw new ErrorWithStack(
prepareErrorMessage(error, 'text', text),
getByTextFn
);
} I assume this returns the first result that satisfies the condition. Compare this to the new const results = queryAllByQuery(instance)(args);
if (results.length > 1) {
throw new ErrorWithStack(getMultipleError(args), getFn);
}
if (results.length === 0) {
throw new ErrorWithStack(getMissingError(args), getFn);
}
return results[0]; In this case, the API contract is different since now an error is thrown if the query finds more than 1 result. This might be an improvement since it is clearer and more aligned with dom-testing-lib but it is different. In the project I'm working on this forces us to re-write our queries from: // FROM
const { getByText } = render(<MyComponent />)
await fireEvent.press(getByText('.cancel'))
// TO
const { getAllByText } = render(<MyComponent />)
await fireEvent.press(getAllByText('.cancel')[0]) Granted this is because we have a design system that results in multiple elements being detected (a button element + a label for the button = 2 results). This is just in case anyone else comes across this. |
I don't think this is correct - If this search is synchronous this might explain why on super deep render trees (like those used in the app in which I work) some tests can take 15s to complete, even if the test timeout is 5s. |
Seems like the transition to by predicate code organisation is mostly done:
To finish the transition I think we should do some final smaller tasks:
@thymikee @MattAgn @AugustinLF wdyt? |
Yes sounds good! I can help on the A11y queries if you want |
Sure on it! |
#965 is merged. Anyone willing to port a11y queries? :) |
@MattAgn you wanted to volunteer so let me know if you want to pick it up :-) otherwise I can work on it. Couple of thoughts on that topic:
export const bindByLabelTextQueries = (
instance: ReactTestInstance
): ByLabelTextQueries => {
const boundGetBy = getBy(instance),
//...
return {
getByLabelText: boundGetBy,
getByA11yHint: boundGetBy,
// ...
}
} Note: that Little repetition hurt nobody, unlike too much abstraction. |
@mdjastrzebski yes i'm on board with all your points |
@MattAgn that works for me 👍🏻 |
@mdjastrzebski should we close this issue now that our PR is merged? |
Describe the Issue
Current queries are organized in files by return type (
getByAPI.js
,queryByAPI.js
,findByAPI.js
) with exception forA11yAPI.js
which is organized by predicate (byA11yLabel, byA11yHint, etc). GenerallygetBy
andgetAllBy
queries are used as core query, withqueryBy
/queryAllBy
andfindBy
/findAllBy
as manually written wrappers aroundgetBy
/getAllBy
quries.There is a lot of repeated code, especially in duplicate
getBy
andgetAllBy
queries as well as manualqueryBy
/queryAllBy
/findBy
/... wrappers.This presents an opportunity to refactor queries so that for each predicate type (
ByText
,byA11yLabel
, etc) there is only function encoding the search algorithm, while all other functions are generated by some generic code.In Testing Library this is achieved by implementing query predicates as
queryAll
function first, and then using genericbuildQueries
function that returnesgetBy
/getAllBy
/etc variants.Benefits
getByTestId
/getAllByTestId
differences.queryAll
version and all other queries will generated for you bybuildQueries
function.Downsides
None found yet.
Considerations
react-test-renderer
find
usesfindAll
under the hood without any query optimization.The text was updated successfully, but these errors were encountered: