Skip to content

Adding getByTextWithType #569

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

Closed
wants to merge 2 commits into from

Conversation

pvinis
Copy link

@pvinis pvinis commented Oct 8, 2020

Summary

This PR adds a much-needed query function by us called getByTextWithType.

We have found that we often need to look for a string inside a specific component that contains it. For example, a component like Header that contains a few texts or our own Button component. In our tests we want to be able to find that Header or Button component, so our options are UNSAFE_getAllByType and get all the Buttons and reference the one we want to test by index, which feels too fragile, or getAllByText and then run up the parent stack to find the Button for each, which feels like the tests do too much "extra" work.

This new query will solve this problem. It is called like so: getByTextWithType('some text', Button) (same for the *All* variation). It works the same as the rest of the get* and getAll* queries for returns and throws, and it will return the Button component that contains a text with 'some text' in it.

The way it works is basically it looks for all texts, same as getAllByText and then runs up the parent stack to see if there is a node with type Button (the second argument in general). If is exists, then it's a successful result. If not, it is ignored.

It could be part of get*ByText with an optional second argument for type, but I didn't want to compicate this PR. I'm happy to do that though if people feel it makes it simpler.

Test plan

I have added tests for both new queries as well as a couple extra sanity check tests. The tests should make usage and results pretty clear.

@thymikee
Copy link
Member

thymikee commented Oct 8, 2020

Hey @pvinis nice to see you here :) I think that getByTextWithType doesn't meet the Testing Library principles. Following other ByType queries, it would need to end up with an UNSAFE_ prefix.

However, we could expose a way to write custom queries, pushing the maintenance and compatibility responsibility to the users. Would you be interested in that? We're discussing exposing root ReactTestInstance, which you could use to construct your query. We could also expose some helpers to make writing such custom queries easier for you.

@pvinis pvinis changed the title finished Adding getByTextWithType Oct 8, 2020
@pvinis
Copy link
Author

pvinis commented Oct 8, 2020

(Sorry for the random titled :p I fixed it.)

Hello! Mm, the UNSAFE_ I guess is consistent for the type checking 🤔.

I think it makes sense to expose this and allow everyone to have their custom queries. I wonder how they would be accessed then. What I don't know is:

const { getByText } = render(<Comp />)

const one = getByText('bla')
const two = getByCustom() // <-- where does that come from? somehow from render? how does it connect?

For this PR specifically, I'd be ok with adding the UNSAFE_ prefix on this, if we still want this to be added. If not, I will look into the exposing of ReactTestInstance and hopefully it can be done quickly so we can start using our custom query.

@thymikee
Copy link
Member

thymikee commented Oct 8, 2020

I can imagine something like this:

const { root } = render(<Comp />);
const customQuery = getByTextWithType(root);
customQuery("text", Button);
// or
getByTextWithType(root)("text", Button)

@thymikee
Copy link
Member

thymikee commented Oct 8, 2020

Or this:

const customRender = render<typeof getByTextWithType>(<Comp />, {extendWithQueries: [getByTextWithType]});
const {getByTextWithType} = customRender(<Comp />)

So we wouldn't have to directly expose root (it would be available to custom queries, but that seems like a fair call for advanced users)

@pvinis
Copy link
Author

pvinis commented Oct 8, 2020

const customRender = render<typeof getByTextWithType>(<Comp />, {extendWithQueries: [getByTextWithType]});
const {getByTextWithType} = customRender(<Comp />)

Yep, that's a good way. We have a wrapper for render anyway, so we can add our own wrappers with the second argument, so it would be very easy to add our custom queries there, and then use them directly like const { customQuery } = ourCustomRenderWrapperFunc(<Comp />) with const ourCustomRenderWrapperFunc = (C) => render(C, {wrapper: WrapperComp, customQueries: {getByTextWithType}).

@pvinis
Copy link
Author

pvinis commented Oct 19, 2020

I'll close this for now.

@pvinis pvinis closed this Oct 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants