Search code examples
reactjstestingjestjsreact-testing-library

Ho do I use a query getByTestId from react-testing-library properly?


I'm trying to test my components with react-testing library.

Some of my components are good with getByTestId query but others aren't.

Examlpe: SideBar component code

export const SideBar: FC<SideBarPropsInterface> = ({ className }) => {
    const [collapsed, setCollapsed] = useState(false)

    const handleToggle = (): void => {
        setCollapsed((prev) => !prev)
    }

    const classNameChecked = className ?? ''

    return (
        <div
            data-testid="sidebar"
            className={classNames(
                styles.sideBar,
                { [styles.collapsed]: collapsed },
                [classNameChecked]
            )}
        >
            <button onClick={handleToggle}>toggle</button>
            <div className={styles.switchers}>
                <ThemeSwitcher />
                <LangSwitcher />
            </div>
        </div>
    )
}

Test for SideBar

describe('SideBar', () => {
    test('render', () => {
        render(<SideBar/>)
        screen.debug()
        expect(screen.getByTestId('sidebar')).toBeInTheDocument()
    })
})

Error

TestingLibraryElementError: Unable to find an element by: [data-testid="sidebar"]

Ignored nodes: comments, script, style
<body>
  <div />
</body>

As you can see test renders just div without attributes.

But my other components are good with it. Like Button component

Button component code

export const Button: FC<ButtonPropsInterface> = ({
    children,
    className,
    theme,
    ...otherProps
}) => {
    
    const classNameChecked = className ?? ''

    return (
        <button
            data-testid="special"
            className={classNames(styles.button, {}, [
                classNameChecked,
                styles[theme as ThemeButton]
            ])}
            {...otherProps}
        >
            {children}
        </button>
    )
}

Test for Button

describe('Button', () => {
    test('render', () => {
        render(<Button>test</Button>)
        screen.debug()
        expect(screen.getByTestId('special')).toBeInTheDocument()
    })
})

Passed(screen.debug)

  console.log
    <body>
      <div>
        <button
          class="button undefined"
          data-testid="special"
        >
          test
        </button>
      </div>
    </body>

Question: what am I doing wrong? I need my SideBar component to pass the test with getByTestId query


Solution

  • Ok. I found a solution. If you have child components inside your parent component, you need to mock them manually.

    In my case I have <LangSwitcher/> and <ThemeSwitchers/> inside <SideBar/>

    RTL doesn't see them until I mock

    jest.mock("widgets/LangSwitcher")
    jest.mock("widgets/ThemeSwitcher")
    
    describe('SideBar', () => {
        test('render', () => {
            render(<SideBar/>)
            screen.debug()
            expect(screen.getByTestId('sidebar')).toBeInTheDocument()
        })
    })