Search code examples
reactjsjestjsreact-testing-library

How to get the result 'toHaveStyle' in testing-library-react?


Testing library react does not catch 'toHaveStyle'.
When I clicked on the 'Content', its children which have a blue color were changed to the red color.

However, in my test, they always have the blue color.

What should I do to solve this problem?

[...]
<Content data-testid={"list-element-content"} id={data.id} toggle={state[data.id - 1]}>
  <div>{data.titleUnBold}</div>
  <BoldTitle>{data.titleBold}</BoldTitle>
</Content>
[...]

const Content = styled.div`
  color: ${ (props) => props.toggle ? "red" : "blue" };
`;

Below the test code:

test("color changed", () => {
  const mockState = [false];
  const mockSwitchGuide = jest.fn();
  const { getAllByTestId, rerender } = render(
    <GuideListPresenter
      data={mockListData}
      state={mockState} 
      onClick={mockSwitchGuide}
    />
  );

  act(() => {
    fireEvent.change(getAllByTestId("list-element-content")[0],{
      target: {toggle: true},
    });
  });

  rerender(
    <GuideListPresenter data={mockListData} state={mockState} onClick={mockSwitchGuide} />
  );
  expect(getAllByTestId("list-element-content")[0].toggle).toEqual(true);  // success 
  expect(getAllByTestId("list-element-content")[0]).toHaveStyle("color: red");   // failed
})

Solution

  • To test the style of your component, you can get it directly from the html document, and see precisely what style is used for a specific element.

    In your example, you would do something like below:

    it('should change color to red on toggle click', () => {
      const { container, getAllByTestId } = render(
        <GuideListPresenter
          data={mockListData}
          state={mockState} 
          onClick={mockSwitchGuide}
        />
      );
    
      // Replace <YOUR_DIV_ID> by your component's id
      let contentDiv = document.getElementById('<YOUR_DIV_ID>');
      let style = window.getComputedStyle(contentDiv[0]);
      expect(style.color).toBe('blue'); // Sometimes, only rgb style type is read here. See the rgb that corresponds to your color if need be.
    
      act(() => {
        fireEvent.change(getAllByTestId("list-element-content")[0],{
          target: {toggle: true},
        });
      });
    
      // Get the updated contentDiv
      contentDiv = document.getElementsByClassName('<YOUR_DIV_CLASS_NAME>');
      style = window.getComputedStyle(contentDiv[0]);
      expect(style.color).toBe('red');
    
      expect(getAllByTestId("list-element-content")[0].toggle).toEqual(true);
    }
    

    Here, to get the style of your element, I am using the element's id. However, it could also work with the element's className, and using the method document.getElementByClassName('YOUR_DIV_CLASS_NAME') instead. Note that the given name here should be unique, either with the id technique, or the className.