A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://callstack.github.io/react-native-testing-library/docs/advanced/testing-env below:

Testing environment - React Native Testing Library

Testing environment#

INFO

This document is intended for a more advanced audience who want to understand the internals of our testing environment better, e.g., to contribute to the codebase. You should be able to write integration or component tests without reading this.

React Native Testing Library allows you to write integration and component tests for your React Native app or library. While the JSX code used in tests closely resembles your React Native app, things are not as simple as they might appear. This document will describe the key elements of our testing environment and highlight things to be aware of when writing more advanced tests or diagnosing issues.

React renderers#

React allows you to write declarative code using JSX, write function or class components, or use hooks like useState. You need to use a renderer to output the results of your components. Every React app uses some renderer:

When you run your tests in the React Native Testing Library, somewhat contrary to what the name suggests, they are actually not using React Native renderer. This is because this renderer needs to be run on an iOS or Android operating system, so it would need to run on a device or simulator.

React Test Renderer#

Instead, RNTL uses React Test Renderer, a specialized renderer that allows rendering to pure JavaScript objects without access to mobile OS and can run in a Node.js environment using Jest (or any other JavaScript test runner).

Using React Test Renderer has pros and cons.

Benefits:

Disadvantages:

It's worth noting that the React Testing Library (web one) works a bit differently. While RTL also runs in Jest, it has access to a simulated browser DOM environment from the jsdom package, which allows it to use a regular React DOM renderer. Unfortunately, there is no similar React Native runtime environment package. This is probably because while the browser environment is well-defined and highly standardized, the React Native environment constantly evolves in sync with the evolution of underlying OS-es. Maintaining such an environment would require duplicating countless React Native behaviors and keeping them in sync as React Native develops.

Element tree#

Calling the render() function creates an element tree. This is done internally by invoking TestRenderer.create() method. The output tree represents your React Native component tree, and each node of that tree is an "instance" of some React component (to be more precise, each node represents a React fiber, and only class components have instances, while function components store the hook state using fibers).

These tree elements are represented by ReactTestInstance type:

interface ReactTestInstance {
  type: ElementType;
  props: { [propName: string]: any };
  parent: ReactTestInstance | null;
  children: Array<ReactTestInstance | string>;

  // Other props and methods
}

Based on: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-test-renderer/index.d.ts

Host and composite components#

One of the most important aspects of the element tree is that it is composed of both host and composite components:

That might initially sound confusing since we put React Native's View in both categories. There are two View components: composite and host. The relation between them is as follows:

The part of the tree looks as follows:

* <View> (composite)
  * <View> (host)
    * children prop passed in JSX

A similar relation exists between other composite and host pairs: e.g. Text , TextInput, and Image components:

* <Text> (composite)
  * <Text> (host)
    * string (or mixed) content

Not all React Native components are organized this way, e.g., when you use Pressable (or TouchableOpacity), there is no host Pressable, but composite Pressable is rendering a host View with specific props being set:

* <Pressable> (composite)
  * <View accessible={true} {...}> (host)
    * children prop passed in JSX
Differentiating between host and composite elements#

Any easy way to differentiate between host and composite elements is the type prop of ReactTestInstance:

You can use the following code to check if a given element is a host one:

function isHostElement(element: ReactTestInstance) {
  return typeof element.type === 'string';
}
Tree nodes#

We encourage you to only assert values on host views in your tests because they represent the user interface view and controls which the user can see and interact with. Users cannot see or interact with composite views as they exist purely in the JavaScript domain and do not generate any visible UI.

Asserting props#

For example, suppose you assert a style prop of a composite element. In that case, there is no guarantee that the style will be visible to the user, as the component author can forget to pass this prop to some underlying View or other host component. Similarly onPress event handler on a composite prop can be unreachable by the user.

function ForgotToPassPropsButton({ title, onPress, style }) {
  return (
    <Pressable>
      <Text>{title}</Text>
    </Pressable>
  );
}

In the above example, user-defined components accept both onPress and style props but do not pass them (through Pressable) to host views, so they will not affect the user interface. Additionally, React Native and other libraries might pass some of the props under different names or transform their values between composite and host components.

Tree navigation#

CAUTION

You should avoid navigating over the element tree, as this makes your testing code fragile and may result in false positives. This section is more relevant for people who want to contribute to our codebase.

You will encounter host and composite elements when navigating a tree of react elements using parent or children props of a ReactTestInstance element. You should be careful when navigating the element tree, as the tree structure for third-party components can change independently from your code and cause unexpected test failures.

Inside RNTL, we have various tree navigation helpers: getHostParent, getHostChildren, etc. These are intentionally not exported, as using them is not recommended.

Queries#

All recommended Testing Library queries return host components to encourage the best practices described above.

Only UNSAFE_*ByType and UNSAFE_*ByProps queries can return both host and composite components depending on used predicates. They are marked as unsafe precisely because testing composite components makes your test more fragile.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4