React component test fails with: TestingLibraryElementError: Found multiple elements by: [data-testid="some-id"]

Viewed 3406

I couldn't find any solution in any other questions similar to mine so I decided to ask you for help.

I have tests to my <Login/> page:

import React from 'react';
import { render } from '../../__test__/utils';
import Login from '.';

test('Renders the Login page', () => { 
  const { getByTestId } = render(<Login />);

  expect(getByTestId('login-page')).toBeInTheDocument(); //WORKS
});

test('Renders disabled submit button by default', () => {
  const { getByTestId } = render(<Login />);

  expect(getByTestId('login-button')).toHaveAttribute('disabled'); // ERROR HERE
});

test('should match base snapshot', () => {
  const { asFragment } = render(<Login />);

  expect(asFragment()).toMatchSnapshot(); //WORKS
});

I am using the 'utils.js' in my tests because I want to wrap every testing component in the providers I am using. Here is how the utils file looks like:

import React, { useState } from 'react';
import { render as rtlRender } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { renderRoutes } from 'react-router-config';
import { Router } from 'react-router-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { ThemeProvider } from '@material-ui/styles';
import { createMemoryHistory } from 'history';
import StylesProvider from '../components/StylesProvider';
import routes from '../routes';
import reducer from '../reducers';

import { theme } from '../theme';

const history = createMemoryHistory();

const render = (
  ui,
  { initialState, store = createStore(reducer, initialState), ...renderOptions } = {}
) => {
  const Wrapper = ({ children }) => {
    const [direction] = useState('ltr');

    return (
      <Provider store={store}>
        <ThemeProvider theme={theme}>
          <StylesProvider direction={direction}>
            <Router history={history}>
              {children}
              {renderRoutes(routes)}
            </Router>
          </StylesProvider>
        </ThemeProvider>
      </Provider>
    );
  };
  return rtlRender(ui, { wrapper: Wrapper, ...renderOptions });
};

export * from '@testing-library/react';
export { render };

Unfortunately, I cannot show the whole app code so I'll make it short. The <Login /> component looks like below:

import React from 'react';
import { makeStyles } from '@material-ui/styles';
import {
  Card, CardContent, CardHeader, Typography, Divider, Grid
} from '@material-ui/core';
import Page from 'src/components/Page';
import LoginForm from './LoginForm';

const Login = () => (
  <Page className={classes.root} title="Login" dataTestId="login-page">
     //here the component body//

          <LoginForm
            afterLoginRoute="/overview"
            loginEndpoint="login"
            userRole={userRoles.USER}
            className={classes.loginForm}
          />
  </Page>
)

In the <LoginForm /> component I have a Material-UI button with data-testid="login-button"

LoginForm:

  return (
    <div>
      <Snackbar open={loginStatus.error} autoHideDuration={6000}>
        <Alert severity="error">
          Se ha producido un error, comprueba los credenciales y prueba de nuevo.
        </Alert>
      </Snackbar>
      <form {...rest} className={clsx(classes.root, className)} onSubmit={handleSubmit}>
        <div className={classes.fields}>
          <TextField
            className={classes.input}
            error={hasError('email')}
            fullWidth
            helperText={hasError('email') ? formState.errors.email[0] : null}
            label="Email"
            name="email"
            onChange={handleChange}
            value={formState.values.email || ''}
            variant="outlined"
          />
          <TextField
            className={classes.input}
            error={hasError('password')}
            fullWidth
            helperText={hasError('password') ? formState.errors.password[0] : null}
            label="ContraseƱa"
            name="password"
            onChange={handleChange}
            type="password"
            value={formState.values.password || ''}
            variant="outlined"
          />
        </div>
        <Button
          className={classes.submitButton}
          color="secondary"
          disabled={!formState.isValid}
          size="large"
          type="submit"
          variant="contained"
          data-testid="login-button"
        >
          Entrar
        </Button>
      </form>
    </div>
  );

Current test result I have is TestingLibraryElementError: Found multiple elements by: [data-testid="login-button"]. I am out of ideas right now. Could this happen because I try to pass the data-testid prop to the <Button /> which is imported from Material-UI library? Then, shouldn't I see other error message? Please help.

0 Answers
Related