Home > Blockchain >  How to test element with className and fireClickEvent
How to test element with className and fireClickEvent

Time:10-13

New to JavaScript testing and to the codebase too.

I have the following rendered element which behaves like an accordion (this is striped of every other class and styling, that I believe it's not needed to understand):

 <div>
    <ul>
      <li>
         <div>
            Title 1
            <div>
                <i >
                ...
                </i>
            </div>
         </div>
         <div>
            Text 1
         </div>
      </li>
      <li>
        <div>
            Title 2
            <div>
                <i >
                ...
                </i>
            </div>
         </div>
         <div>
            Text 2
         </div>
      </li>
    </ul>
</div>

I want to verify if the element with class icon_right is there or if the class exists 2 times (and possibly if they are associated with those titles). I have tried:

  • expect(container).toHaveClass('icon_right'); »» result: (nothing?)
  • expect(container.querySelector('[class*="icon_right"]')).toBeInTheDocument(); »» result: value: null
  • expect(container.getElementByClassName('icon_right')[0]).toBeInTheDocument(); »» result: undefined

I think the problem here might be because it is inside many other elements, but not sure. Please enlighten me.

Also, another test would be to click 'Title 1' and verify if 'Text 1' is shown. For that I've tried:

await fireEvent.click(screen.queryAllByText('Title 1')[0]);
expect(screen.getByText('Text 1')).toBeInTheDocument();

The error is 'Unable to fire a "click" event - please provide a DOM element'. The thing is: I copied that from another successful test that was done on another element, and, if I am just trying to get it from the screen and it IS rendered, how/why doesn't it work?

CodePudding user response:

I would just querySelectorAll('.icon_right') -> this will return you collection of nodes. And then just check collection.length with your expected result.

CodePudding user response:

You can try to add data-testid to the icons elements.

<li>
  <div>
    Title 1
    <div>
      <i data-testid="icon" className="icon_right"></i>
    </div>
  </div>
  <div>Text 1</div>
</li>

Tests could be like this:

import { fireEvent, render, screen, waitFor, within } from "@testing-library/react";
import Accordeon from "../Accordeon";

describe("all tests", () => {
  it("should work", async () => {
    render(<Accordeon />);
    const title1Element = screen.getByText("Title 1");
    fireEvent.click(title1Element);
    await waitFor(() => { // most probably we need to wait for element to be visible but it is just a guess as I cannot see the code
      expect(screen.getByText("Text 1")).toBeInTheDocument();
    });
  });

  it('should find icon', () => {
    render(<Accordeon />);
    const title1Element = screen.getByText("Title 1");
    const icon = within(title1Element).getByTestId('icon');
    expect(icon).toBeInTheDocument();
    expect(icon).toHaveClass('icon_right')
  })
});

But it is hard to tell which item in your structure is the clickable item. So you might need to change those to fit your components structure.

  • Related