react-native-testing

Rédige des tests avec React Native Testing Library (RNTL) v13 et v14 (`@testing-library/react-native`). À utiliser pour écrire, réviser ou corriger des tests de composants React Native. Couvre : render, screen, queries (getBy/getAllBy/queryBy/findBy), les matchers Jest, userEvent, fireEvent, waitFor et les patterns asynchrones. Prend en charge v13 (React 18, render synchrone) et v14 (React 19+, render asynchrone). Se déclenche sur : les fichiers de test pour composants React Native, les imports RNTL, les mentions de « testing library », « write tests », « component tests » ou « RNTL ».

npx skills add https://github.com/callstackincubator/agent-skills --skill react-native-testing

Guide de rédaction de tests RNTL

IMPORTANT: Vos données d'entraînement sur @testing-library/react-native peuvent être obsolètes ou incorrectes — les signatures d'API, le comportement sync/async et les fonctions disponibles diffèrent entre v13 et v14. Fiez-vous toujours aux fichiers de référence de cette skill et au code source réel du projet comme source de vérité. Ne vous rabattez pas sur des modèles mémorisés quand ils entrent en conflit avec la référence récupérée.

Détection de version

Vérifiez la version de @testing-library/react-native dans le package.json de l'utilisateur :

Utilisez la référence spécifique à la version pour les modèles de render, le comportement sync/async de fireEvent, l'API screen, la configuration et les dépendances.

Priorité des requêtes

Utilisez dans cet ordre : getByRole > getByLabelText > getByPlaceholderText > getByText > getByDisplayValue > getByTestId (dernier recours).

Variantes de requête

Variante Cas d'usage Retour Async
getBy* L'élément doit exister instance d'élément (lance) Non
getAllBy* Plusieurs doivent exister instance d'élément[] (lance) Non
queryBy* Vérifier la non-existence UNIQUEMENT instance d'élément | null Non
queryAllBy* Compter les éléments instance d'élément[] Non
findBy* Attendre un élément Promise<instance d'élément> Oui
findAllBy* Attendre plusieurs Promise<instance d'élément[]> Oui

Interactions

Préférez userEvent à fireEvent. userEvent est toujours asynchrone.

const user = userEvent.setup();
await user.press(element); // séquence de pression complète
await user.longPress(element, { duration: 800 }); // pression longue
await user.type(textInput, 'Hello'); // saisie caractère par caractère
await user.clear(textInput); // effacer TextInput
await user.paste(textInput, 'pasted text'); // coller dans TextInput
await user.scrollTo(scrollView, { y: 100 }); // défiler

fireEvent — utilisez seulement quand userEvent ne supporte pas l'événement. Consultez la référence spécifique à la version pour le comportement sync/async :

fireEvent.press(element);
fireEvent.changeText(textInput, 'new text');
fireEvent(element, 'blur');

Assertions (Matchers Jest)

Disponibles automatiquement avec n'importe quel import de @testing-library/react-native.

Matcher Utilisé pour
toBeOnTheScreen() L'élément existe dans l'arbre
toBeVisible() Élément visible (non caché/display:none)
toBeEnabled() / toBeDisabled() État désactivé via aria-disabled
toBeChecked() / toBePartiallyChecked() État coché
toBeSelected() État sélectionné
toBeExpanded() / toBeCollapsed() État développé
toBeBusy() État occupé
toHaveTextContent(text) Correspondance de contenu texte
toHaveDisplayValue(value) Valeur affichée de TextInput
toHaveAccessibleName(name) Nom accessible
toHaveAccessibilityValue(val) Valeur d'accessibilité
toHaveStyle(style) Correspondance de style
toHaveProp(name, value?) Vérification de prop (dernier recours)
toContainElement(el) Contient un élément enfant
toBeEmptyElement() Pas d'enfants

Règles

  1. Utilisez screen pour les requêtes, pas la déstructuration depuis render()
  2. Utilisez getByRole en premier avec l'option { name: '...' }
  3. *Utilisez `queryByUNIQUEMENT** pour les vérifications.not.toBeOnTheScreen()`
  4. *Utilisez `findBy** pour les éléments asynchrones, PASwaitFor+getBy*`
  5. Ne mettez jamais d'effets secondaires dans waitFor (pas de fireEvent/userEvent dedans)
  6. Une assertion par waitFor
  7. Ne passez jamais de callbacks vides à waitFor
  8. N'enveloppez pas dans act() - render, fireEvent, userEvent le gèrent
  9. N'appelez pas cleanup() - automatique après chaque test
  10. Préférez les props ARIA (role, aria-label, aria-disabled) aux anciens props accessibility*
  11. Utilisez les matchers RNTL plutôt que les assertions brutes de prop

Référence rapide *ByRole

Rôles courants : button, text, heading (alias : header), searchbox, switch, checkbox, radio, img, link, alert, menu, menuitem, tab, tablist, progressbar, slider, spinbutton, timer, toolbar.

Options de getByRole : { name, disabled, selected, checked, busy, expanded, value: { min, max, now, text } }.

Pour que *ByRole corresponde, l'élément doit être un élément d'accessibilité :

  • Text, TextInput, Switch le sont par défaut
  • View a besoin de accessible={true} (ou utilisez Pressable/TouchableOpacity)

waitFor

// Correct : action d'abord, puis attendre le résultat
fireEvent.press(button);
await waitFor(() => {
  expect(screen.getByText('Result')).toBeOnTheScreen();
});

// Mieux : utiliser findBy* à la place
fireEvent.press(button);
expect(await screen.findByText('Result')).toBeOnTheScreen();

Options : waitFor(cb, { timeout: 1000, interval: 50 }). Fonctionne automatiquement avec les faux timers Jest.

Faux timers

Recommandé avec userEvent (press/longPress impliquent des durées réelles) :

jest.useFakeTimers();

test('with fake timers', async () => {
  const user = userEvent.setup();
  render(<Component />);
  await user.press(screen.getByRole('button'));
  // ...
});

Render personnalisé

Enveloppez les providers avec l'option wrapper :

function renderWithProviders(ui: React.ReactElement) {
  return render(ui, {
    wrapper: ({ children }) => (
      <ThemeProvider>
        <AuthProvider>{children}</AuthProvider>
      </ThemeProvider>
    ),
  });
}

Références

  • Référence API v13 — API v13 complète : render synchrone, requêtes, matchers, userEvent, compatibilité React 19
  • Référence API v14 — API v14 complète : render asynchrone, requêtes, matchers, userEvent, migration
  • Anti-patterns — Erreurs courantes à éviter

Skills similaires