简体   繁体   中英

React Testing Library, Component Unit Tests

I am trying to build a test unit for my simple React Application using React Testing Library. I readed all docs and get stuck in it.

API was created by create React app. One of the feature is that user can change theme. There is setTheme hook that going to change theme "dark" and "light".

App.js

const App = () => { 
const [theme, setTheme] = useState('dark'); 
return ( <div>
           <Header theme={theme} setTheme={setTheme} />
        </div>)
};

Header.js

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

const Header = props => {
  return (
    <header data-testid="header">
      <h1><span className="highlight">Github Users</span></h1>
      {props.theme === "dark" ? 
        <FontAwesomeIcon data-testid="button" icon="sun" size="2x" color="#dcba31"  onClick={ () => props.setTheme('light') }/>
        :  <FontAwesomeIcon icon="moon" size="2x" color="#1c132d" onClick={ () => props.setTheme('dark') }/>}
    </header>
  );
}
export default Header;

In Header component I added arrow function that changes color of theme.

Now I am trying to write a test that's gonna test Header Component. Expected result is that after first render Header component shall render icon "sun". After user click on it header shall return icon "moon".

There is something that i try but it's not working as I mention.

Header.test.js

import React from 'react';
import { render, cleanup } from "@testing-library/react"
import '@testing-library/jest-dom/extend-expect';
import { act } from "react-dom/test-utils";


import Header from '../components/Header';

afterEach(cleanup);

describe("Header Component", () => { 
    it("first render should return a sun icon", () => {
        const {getByTestId } = render(<Header />)
        expect(getByTestId("header"). // What method uses here? To check if it is icon sun or moon ? )

    })
    it("after mouse click event should return a moon icon", () => {
        const button = document.querySelector("svg"); // it is correct way to add a svg element as a button ?
        act( () => {
            button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
        })
        expect(getByTestId("header").  // again what to write here to test it after click ?
    })
})

I am sure that there is some other way to check first render and then after click what's Header component rendering. I think that problem is that there is another Component that is rendered conditionaly. If it is text there is no problem, but after render there is svg element with some attributes like icon="sun" / icon="moon".

Live version of project

Github Repo Link

Questions:

  1. How to properly test that Header component?
  2. How to pass props in test for example I want to use that setTheme hook in test how to do it?

There's many ways to do this and I can recommend the articles here https://kentcdodds.com/blog/?q=test to get you started. As for your current set-up I'd change some stuff that I find helpful writing unit tests:

  • Use data-testid to find elements, eg "first render should return a sun icon" can be confirmed by expect(getByTestId('svg-sun')).toBeDefined() , which is a pattern I like
  • Structure your it 's like stubbing-rendering-assertions and only test one thing in each test, for instance, in your second it you're lacking a rendering part of the test

Regarding your question regarding passing the props, you can pass it as render(<Header theme={theme} setTheme={setThemeStub}/>) where const setThemeStub = jest.fn() . This allows you to make assertions as expect(setThemeStub).toBeCalledWith(...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM