Closed erheron closed 9 months ago
@erheron Could you post a minimal repro for your issue?
You should not inspect children
for such purpose, as they hold some internal types. Try using toBeEmptyElement()
matcher.
Yeah, toBeEmptyElement
seems to be working 🤔
For the record, this is what I had in mind (omitting the whole renderWithProviders
topic):
interface Props {
username: string;
}
function Component(props: Props) {
if (props.username === '') {
return null;
}
return (
<View testID="main_component_view">
<Text> {props.username} </Text>
</View>
);
}
describe('Test Component', () => {
test('Renders null if username is an empty string', () => {
render(<Component username="" />);
// WHAT TO EXPECT HERE?
});
});
It would be nice if the jest-native matchers contained more inline documentation 🙏🏻
This is what it looks like in my node_modules
rn -- only toBeOnTheScreen
contains the explanation 😒
export interface JestNativeMatchers<R> {
/**
* Assert whether an element is present in the element tree or not.
*/
toBeOnTheScreen(): R;
toBeChecked(): R;
toBeCollapsed(): R;
toBeDisabled(): R;
toBeBusy(): R;
toBeEmptyElement(): R;
toBeEnabled(): R;
toBeExpanded(): R;
toBePartiallyChecked(): R;
toBeSelected(): R;
toBeVisible(): R;
toContainElement(element: ReactTestInstance | null): R;
toHaveAccessibilityValue(expectedValue: AccessibilityValueMatcher): R;
toHaveAccessibleName(expectedName?: TextMatch, options?: TextMatchOptions): R;
toHaveDisplayValue(expectedValue: TextMatch, options?: TextMatchOptions): R;
toHaveProp(name: string, expectedValue?: unknown): R;
toHaveStyle(style: StyleProp<Style>): R;
toHaveTextContent(expectedText: TextMatch, options?: TextMatchOptions): R;
}
Let's close this -- toBeEmptyElement
does what I need. Sorry for hustle 🙇🏻
Would screen.toBeNull()
work?
describe('Test Component', () => {
test('Renders null if username is an empty string', () => {
render(<Component username="" />);
screen.root.toBeNull();
});
});
Yeah I think it would.
I actually ended up implementing a custom util very similar to what you wrote:
/// file TestingUtils.tsx
export function expectScreenToBeEmpty(){
expect(screen.getByTestId('artificial_root')).toBeEmptyElement();
}
/// file renderWithProviders.tsx
function renderWithProviders(ui, options){
const Wrapper = <View testID="artificial_root>; // and more providers
return render(ui, { wrapper: Wrapper, options});
}
/// file test.tsx
test('Test empty render', () => {
TestUtils.expectScreenToBeEmpty;
}
@erheron whatever floats your boat ⛵️
I think that screen.root.toBeNull()
is the most idiomatic approach (assuming it works 🤣). It says that the component you rendered resulted in null (non-existent) root host component.
re missing TSDocs: yeah, I need to add them 👍🏻
But instead of checking the nullability of the component why not check that the string you would look for is not there by queryByText. I just wondered about your case to broad my perspective @erheron
@guvenkaranfil There are some cases when checking for empty render or empty children might be better, e.g., when testing a component displaying a notification dot in the UI. It does not have a text representation, and you want to check whether the element is rendered depending on the notification state. As there are many ways to test things, you could also check for tesiID
in such cases.
Hmm makes sense thanks for the reply @mdjastrzebski
But instead of checking the nullability of the component why not check that the string you would look for is not there by queryByText. I just wondered about your case to broad my perspective @erheron
@guvenkaranfil imagine a component, originally looking like this:
function Component(props){
if(!validate(props)){ return null; }
return (<View testID="component_root"> .... </View>);
}
Now, writing a test which checks that e.g. screen.getByTestID("component_root")
is not on the screen, will not get us far -- how do I really know what is on a screen? I have to be sure that it's null
.
Moreover, a component may change in the future to something like this:
function Component(newProps){
if(!anotherValidate(newProps)){ return <PlaceholderUI />; }
return (<View testID="component_root"> .... </View>);
}
Now, a test which checks for null
'ish render would "catch" this change and that test would probably need to be updated.
On the contrary, a test which checks that something is not on the screen, wouldn't reflect what this component is doing anymore
Thanks for detailed explanation. Yeap it much more make sense that we might want to check nullability
@erheron whatever floats your boat ⛵️
I think that
screen.root.toBeNull()
is the most idiomatic approach (assuming it works 🤣). It says that the component you rendered resulted in null (non-existent) root host component.re missing TSDocs: yeah, I need to add them 👍🏻
@mdjastrzebski oh right, screen.root.toBeNull
of course won't work, since we render some providers in our renderWithProviders
function.
Ask your Question
I have a component which renders
null
if some data validation check do not pass. I'd like to test this behavior using RNTL. Question: how do I do this? For the record, we are using a customrenderWithProviders
function, as suggested in Redux docsI thought about wrapping the element I'm testing in a
<View testId="artificial_root_view">
and then somehow verifying that this view has no children. But when I tried to do the following 👇🏻I got the following error: