React-testing-library: Can't access prop values

Created on 26 Jun 2020  路  2Comments  路  Source: testing-library/react-testing-library

I have been writing a test for my alert.js. I need to access prop value to test its severity. I tried lots of things. But failed every time.

import React from 'react';
import PropTypes from 'prop-types';
import { Snackbar } from '@material-ui/core';
import { Alert as MuiAlert } from '@material-ui/lab';

const Alert = (props) => {
    return (
        <Snackbar
            open={props.open}
            autoHideDuration={3000}
            onClose={props.onClose}
            data-testid='component-alert'
        >
            <MuiAlert
                onClose={props.onClose}
                severity={props.severity}
                data-testid='alert-message'
            >
                {props.message}
            </MuiAlert>
        </Snackbar>
    );
};

Alert.propTypes = {
    message: PropTypes.string.isRequired,
    severity: PropTypes.oneOf(['error', 'warning', 'info', 'success'])
        .isRequired,
    open: PropTypes.bool.isRequired,
    onClose: PropTypes.func.isRequired,
};

export default Alert;

alert.test.js


import React from 'react';
import { render, cleanup } from '@testing-library/react';
import Alert from '../Alert';

const mockFunc = jest.fn();
const defaultProps = {
    message: 'abc',
    severity: 'error',
    open: true,
    onClose: mockFunc,
};

const setup = (props = {}) => {
    const setupProps = { ...defaultProps, props };
    return render(<Alert {...setupProps} />);
};

it('should render without error', () => {
    const { asFragment } = setup();
    expect(asFragment(<Alert {...defaultProps} />)).toMatchSnapshot();
});

describe('should render components without error', () => {
    let component;
    beforeEach(() => {
        component = setup();
    });
    afterEach(() => {
        cleanup();
    });
    test('renders main component', () => {
        const { getByTestId } = component;
        expect(getByTestId('component-alert')).toBeTruthy();
    });
    test('renders message section', () => {
        const { getByTestId } = component;
        expect(getByTestId('alert-message')).toBeTruthy();
    });
});

describe('should render with correct values', () => {
    let component;
    beforeEach(() => {
        component = setup();
    });
    afterEach(() => {
        cleanup();
    });
    test('render alert message', () => {
        const { getByTestId, container } = component;

        expect(getByTestId('alert-message').textContent).toBe('abc');
    });
    test('render correct severity', () => {
render(<Alert {...defaultProps}/>
      /---How to access my severity prop value here ---/
    });
});
question

Most helpful comment

With testing library, you're encouraged to test the user's interaction with the screen. Relying on the React component data like state or props leads to brittle tests that depend on implementation detail and don't provide as much value to users, so testing library actively discourages this by not exposing the data. Instead you have some less brittle options here:

  1. Remove this test since it's just a presentation component and most of the logic is in Material UI
  2. Just snapshot the component if you need to make sure it's always rendering the same thing, I believe styles are included with this
  3. If you want to integration test with Material UI to make sure that your use is showing the severity without having to snapshot the entire component, you can use expect().toHaveStyle('color: someMaterialSeverityColor')

All 2 comments

Hi @Dev-Aman7 thanks for opening this issue 馃槃

What you want to do is really discouraged by testing-library.
I suggest you to read this article that explains why.

With testing library, you're encouraged to test the user's interaction with the screen. Relying on the React component data like state or props leads to brittle tests that depend on implementation detail and don't provide as much value to users, so testing library actively discourages this by not exposing the data. Instead you have some less brittle options here:

  1. Remove this test since it's just a presentation component and most of the logic is in Material UI
  2. Just snapshot the component if you need to make sure it's always rendering the same thing, I believe styles are included with this
  3. If you want to integration test with Material UI to make sure that your use is showing the severity without having to snapshot the entire component, you can use expect().toHaveStyle('color: someMaterialSeverityColor')
Was this page helpful?
0 / 5 - 0 ratings

Related issues

addamove picture addamove  路  3Comments

suresh777 picture suresh777  路  3Comments

julienw picture julienw  路  4Comments

chasen-bettinger picture chasen-bettinger  路  3Comments

jaredmeakin picture jaredmeakin  路  3Comments