2

I'm facing an issue where my test fails to find an element by text after I added the Select UI component from gluestack-ui to my React Native component.

Before adding the Select, my test works fine:

test-utils.tsx

import React from 'react'
import {render} from '@testing-library/react-native'
import { GluestackUIProvider } from "@/components/ui/gluestack-ui-provider";
import fs from 'fs';

const AllTheProviders = ({children}) => {
  return (
    <GluestackUIProvider>
        {children}
    </GluestackUIProvider>
  )
}

const customRender = (ui, options?) => {
  const view = render(ui, {wrapper: AllTheProviders, ...options})

  const style = document.createElement('style');
  style.innerHTML = fs.readFileSync('./output.css', 'utf8');
  document.head.appendChild(style);

  return view;
}
// re-export everything
export * from '@testing-library/react-native'

// override render method
export {customRender as render}

My component

import React, { useState } from 'react';
import { View, FlatList } from 'react-native';
import { Text } from '@/components/ui/text';
import { Input, InputField } from '@/components/ui/input';
import { Heading } from '../ui/heading';

export const JamSessionsBanner = ({ sessions }) => {
  const [lieu, setLieu] = useState('');
  const [date, setDate] = useState('');

  const filteredSessions = sessions.filter((session) => {
    const matchesLieu = lieu ? session.lieu.toLowerCase().includes(lieu.toLowerCase()) : true;
    const matchesDate = date ? new Date(session.date).toDateString() === new Date(date).toDateString() : true;
    return matchesLieu && matchesDate;
  });

  return (
    <View style={{ padding: 16 }}>
      <Heading>Upcoming JAM Sessions</Heading>
      <FlatList
        data={filteredSessions}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <View style={{ marginBottom: 16 }}>
            <Text>{item.lieu}, {item.ville}</Text>
            <Text>{new Date(item.date).toLocaleString()}</Text>
          </View>
        )}
      />
    </View>
  );
};

The data

export const mockSessions = [
  {
    id: '1',
    date: '2024-10-18T19:30:00',
    lieu: 'Le Café',
    ville: 'Paris',
    description: 'Session de jam ouverte à tous.',
    musiciens: ['John Doe', 'Jane Smith'],
    popularité: 100,
    genre: 'reggae',
  },
  {
    id: '2',
    date: '2024-10-20T20:00:00',
    lieu: 'La Ska Factory',
    ville: 'Lyon',
    description: 'Jam session ska.',
    musiciens: ['Paul Dupont', 'Marie Lafont'],
    popularité: 80,
    genre: 'ska',
  },
];

The jest config

module.exports = {
  preset: 'react-native',
  transform: {
    '^.+\\.tsx?$': 'babel-jest',
  },
  setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|svg)$': 'jest-transform-stub',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
  testEnvironment: 'jsdom',
  testPathIgnorePatterns: [
    '<rootDir>/node_modules/',
    '<rootDir>/e2e/',
    "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|@gluestack-ui/*|@gluestack-style/*|@legendapp/*|react-native-svg)",
  ],
};

The test (it pass):

import { render, screen } from '../../test-utils';
import { JamSessionsBanner } from './JamSessionsBanner';
import { mockSessions } from './jam.mock';

test('renders sessions correctly', () => {
  render(<JamSessionsBanner sessions={mockSessions} />);
  expect(screen.getByText(/Le Café, Paris/i)).toBeTruthy();
});

After adding the Select component, the test fails:

import React, { useState } from 'react';
import { View, FlatList } from 'react-native';
import { Text } from '@/components/ui/text';
import { Input, InputField } from '@/components/ui/input';
import { Heading } from '../ui/heading';
import {
  Select,
  SelectBackdrop,
  SelectContent,
  SelectIcon,
  SelectInput,
  SelectItem,
  SelectPortal,
  SelectTrigger
} from '@/components/ui/select';
import { ChevronDownIcon } from '../ui/icon';

export const JamSessionsBanner = ({ sessions }) => {
  const [lieu, setLieu] = useState('');
  const [date, setDate] = useState('');
  const [selectedVille, setSelectedVille] = useState('Partout');
  const villes = ['Partout', ...new Set(sessions.map(session => session.ville))];

  const filteredSessions = sessions.filter((session) => {
    const matchesLieu = lieu ? session.lieu.toLowerCase().includes(lieu.toLowerCase()) : true;
    const matchesDate = date ? new Date(session.date).toDateString() === new Date(date).toDateString() : true;
    return matchesLieu && matchesDate;
  });

  return (
    <View style={{ padding: 16 }}>
      <Heading>
        Upcoming JAM Sessions
        <Select selectedValue={selectedVille} onValueChange={setSelectedVille}>
          <SelectTrigger variant="outline">
            <SelectInput placeholder="Filter by city" />
            <SelectIcon as={ChevronDownIcon} />
          </SelectTrigger>
          <SelectPortal>
            <SelectBackdrop />
            <SelectContent>
              {villes.map(ville => (
                <SelectItem key={ville} label={ville} value={ville} />
              ))}
            </SelectContent>
          </SelectPortal>
        </Select>
      </Heading>
      <FlatList
        data={filteredSessions}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <View style={{ marginBottom: 16 }}>
            <Text>{item.lieu}, {item.ville}</Text>
            <Text>{new Date(item.date).toLocaleString()}</Text>
          </View>
        )}
      />
    </View>
  );
};

The test now fails with the following error:

Unable to find an element with text: /Le Café, Paris/i

The complete console output:

FAIL  components/JamSessionsBanner/JamSessionsBanner.test.tsx (5.291 s)
  JamSessionsBanner
    ✕ renders sessions correctly (726 ms)

  ● JamSessionsBanner › renders sessions correctly

    Unable to find an element with text: /Le Café, Paris/i

    <View>
      <View>
        <RCTText
          accessibilityRole="header"
          accessible={true}
        >
          Upcoming JAM Sessions
          <View>
            <View
              accessible={true}
              role="button"
            >
              <TextInput
                aria-hidden={true}
                importantForAccessibility="no"
                placeholder="Filter by city"
                value="Partout"
              />
              <RNSVGSvgView
                role="img"
              >
                <RNSVGGroup>
                  <RNSVGGroup>
                    <RNSVGPath />
                  </RNSVGGroup>
                </RNSVGGroup>
              </RNSVGSvgView>
            </View>
          </View>
        </RCTText>
        <RCTScrollView>
          <RCTScrollContentView>
            <View>
              <View>
                <RCTText
                  accessible={true}
                >
                  Le Café
                  , 
                  Paris
                </RCTText>
                <RCTText
                  accessible={true}
                >
                  18/10/2024 19:30:00
                </RCTText>
              </View>
            </View>
            <View>
              <View>
                <RCTText
                  accessible={true}
                >
                  La Ska Factory
                  , 
                  Lyon
                </RCTText>
                <RCTText
                  accessible={true}
                >
                  20/10/2024 20:00:00
                </RCTText>
              </View>
            </View>
          </RCTScrollContentView>
        </RCTScrollView>
      </View>
    </View>

      10 |     render(<JamSessionsBanner sessions={mockSessions} />);
      11 |     // expect(screen.getByText(/Session de jam ouverte à tous/i)).toBeTruthy();
    > 12 |     expect(screen.getByText(/Le Café, Paris/i)).toBeTruthy();
         |                   ^
      13 |   });
      14 |
      15 |   // test('displays empty state when no sessions are available', async () => {

      at Object.getByText (components/JamSessionsBanner/JamSessionsBanner.test.tsx:12:19)
      at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17)
      at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9)
      at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:7)
      at Object.<anonymous> (node_modules/@babel/runtime/helpers/asyncToGenerator.js:14:12)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        6.34 s

What I’ve tried:

  • Ensured that @testing-library/react-native is configured correctly and that the custom render includes the necessary context providers.
  • I've tried to add waitFor in my test.
  • The issue seems to arise only after adding the Select component. Without it, everything works as expected.
  • I've checked the Select rendering and functionality in the app, and it works correctly when manually tested.

Does anyone know why @testing-library/react-native might not be able to find the text after adding Select?

If you have any insights into why adding Select could cause this issue, or if I'm missing something in the testing setup, I’d appreciate the help!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.