DEV Community

Jagoda Bieniek
Jagoda Bieniek

Posted on

1 1 1 1

How to Test stopPropagation() in React Testing Library

๐Ÿš€ Introduction

Ensuring stopPropagation() works correctly in React applications is crucial when handling nested click events. Instead of checking if stopPropagation() was explicitly called, the best approach is to test its effectโ€”whether the event propagates or not.

This article explores:

โœ… The best approach to testing stopPropagation() (checking event propagation).

โœ… An alternative method using event mocking.

โœ… Which method is better and when to use each approach.

๐Ÿ›  Best Approach: Testing the Effect of stopPropagation()

The recommended way to test stopPropagation() is to wrap the tested component inside a parent <div> with an onClick handler and check whether the event reaches the parent.

Example: Testing Propagation Prevention

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { FormElementsList } from "@/components/FormElementsList";

it("stops propagation when an element is clicked", async () => {
  const onOuterClick = jest.fn();

  render(
    <div onClick={onOuterClick}>
      <FormElementsList elementsList={[{ name: "Text Input", type: "text", icon: <span>๐Ÿ“</span> }]} />
    </div>
  );

  const textInputElement = screen.getByText("Text Input");
  await userEvent.click(textInputElement);

  expect(onOuterClick).toHaveBeenCalledTimes(0); // Ensures event does not propagate
});
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Why This Works ?

  • The parent <div> has an onClick handler (onOuterClick).

  • If stopPropagation() is correctly applied inside FormElementsList, clicking on an element should not trigger onOuterClick.

  • The assertion expect(onOuterClick).toHaveBeenCalledTimes(0) ensures the event was stopped successfully.

๐Ÿ›  Alternative: Mocking stopPropagation()

If you need to directly verify that stopPropagation() was called, you can mock the event and track the function call.

Example: Mocking stopPropagation()

import { render, screen } from "@testing-library/react";
import { FormElementsList } from "@/components/FormElementsList";

it("calls stopPropagation when an element is clicked", async () => {
  render(<FormElementsList elementsList={[{ name: "Text Input", type: "text", icon: <span>๐Ÿ“</span> }]} />);

  const textInputElement = screen.getByText("Text Input");

  const event = new MouseEvent("click", { bubbles: true });
  jest.spyOn(event, "stopPropagation");

  textInputElement.dispatchEvent(event);

  expect(event.stopPropagation).toHaveBeenCalled();
});
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“Œ Why This Works ?

  • jest.spyOn(event, "stopPropagation") tracks whether the function is called.

  • dispatchEvent(event) manually triggers the click event.

  • expect(event.stopPropagation).toHaveBeenCalled() ensures stopPropagation() was executed.

๐Ÿ›  Which Method Should You Use?

Method โœ… Pros โŒ Cons
1. Testing Effect (Wrapper <div>) Tests real user behavior Doesnโ€™t confirm stopPropagation() was explicitly called
2. Mocking stopPropagation() Confirms stopPropagation() is called Tests implementation rather than behavior

๐Ÿš€ Recommended Approach

Prioritize testing real behavior over implementation details for better maintainability!

๐Ÿ’ฌ Have you used different methods for testing event propagation? Share your thoughts in the comments!

Billboard image

Deploy and scale your apps on AWS and GCP with a world class developer experience

Coherence makes it easy to set up and maintain cloud infrastructure. Harness the extensibility, compliance and cost efficiency of the cloud.

Learn more

Top comments (0)

๐Ÿ‘‹ Kindness is contagious

Please leave a โค๏ธ or a friendly comment on this post if you found it helpful!

Okay