react-native-testing-library: Error: Unable to find an element with text: "My text", while that text exist.
Describe the bug
getByText
can find element if text render component with text as not children (See “Steps to Reproduce” below)
-const Trans = p => p.i18nKey; // can find (error)
+const Trans = p => p.children; // everything ok
Expected behavior
I see in debug output (see screenshot below) that text exists! But API can find it( It should work properly!
Steps to Reproduce
test('test', () => {
const { Text } = require('react-native');
const { render } = require('@testing-library/react-native');
const Trans = p => p.i18nKey;
const screen = render(
<Text>
<Trans i18nKey="My text" />
</Text>,
);
screen.debug();
expect(screen.getByText('My text')); // Error: Unable to find an element with text: My text
});
Screenshots
Output:
Versions
npmPackages:
@testing-library/react-native: ^7.2.0 => 7.2.0
react: 17.0.2 => 16.13.1
react-native: 0.66.4 => 0.66.4
react-test-renderer: 17.0.2 => 17.0.2
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 36 (15 by maintainers)
@AugustinLF easy to reproduce but not easy to fix?
@AugustinLF I know that this is a feature request. But is is possible to have the
.debug()
run automatically when agetBy*
matcher fails? Recallreact-testing-library
had that and it was really useful to see how the component looks when debugging why it can’t get a hold of it.I (or whoever’s interested in) just need to take the time, but I don’t think it should be very hard. I’ll try to do that later this week, or next week
@pierrezimmermannbam I refactored back into
toJSON
method onReactTestInstance
and I’ve submitted PR: https://github.com/facebook/react/pull/25329Let’s see how the review goes…
Not sure this is easy to fix, the type of <Trans i18nKey=“text”/> isn’t string so the getChildrenAsText method is looking for strings in its children but it doesn’t have any. For this to work it would require to be able to tell that it renders as a string but i’m not sure it’s easily doable.
@retyui this can be fixed on your end by mocking the Trans component like this
However if there is an effective way to fix this it would be very nice, or maybe it could be documented somewhere
@pierrezimmermannbam I’ve started with implementing
toJSON
as a method onReactTestInstance
, however I’ve encountered two issues that made free function a more natural approach:testInstanceToJSON
is recursive, as it needs to call itself for child nodes, and that requires ability to pass node on which to run the functiontestInstanceToJSON
accepts eitherReactTestInstance | string
as sometimes children might be string. Particular there was one existing unit test forrenderer.toJSON()
method that I could not duplicate asrenderer.root.toJSON()
becauserenderer.root
was actually astring
.Thinking about this after your comment, I think that point 1 might be solvable by invoking
child.toJSON()
fromtestInstance.toJSON()
and adding child type checks forstring
values. I will review my code tomorrow to see which feels like a better API.@mdjastrzebski The following implementation seems to work
You were right it does look like it only works on host component
@nanda-kumar-k the posted errors seems to concern React Testing Library, and not React Native Testing Library, as the stack trace mentions
@testing-library/dom
and you use HTML elements.@mdjastrzebski I think it is a very interesting approach, it could event be possible to still use the reactTestInstance.findAll method and then only use the ReactTestRendererJSON type for the getChildrenAsText method which would be a way less significant change. I’ll try it and if it works ask on the React test renderer repo whether it is a change they are willing to make
@AugustinLF @thymikee I have made some progress on this, I opened a draft pr but I’ve hit an issue. The queries by text work fine using the json representation but there are some problems.
First, I still need to get the ReactTestInstance from the renderer.root because the instances in the ReactTestRendererTree type are in fact not of type ReactTestInstance and do not have parents which is problematic for the fireEvent. I was able to fix this by finding the ReactTestInstance matching the result of the search though I’m not entirely sure it is reliable.
The second issue is with within. For within to work, the queries return type and what is used to build the api need to be of the same type and I broke that by building queries with a ReactTestRenderer type and returning the same type as before. It would be doable to have the following type :
However this would require to change not only the byText queries but all of them, which is more complex but shouldn’t be too much of an issue if well refactored. It would change the type of the api but not cause a breaking change as we’d be only adding a new field so it shouldn’t be too problematic.
So before going further I wanted to have your inputs on this and make sure the implementation I started was what you also had in mind