nerdyman/react-compare-slider

Jest `Cannot find module 'react-compare-slider' (v3.X)

stevebutler2210 opened this issue · 6 comments

Running version 3.X of the package is working fine in Storybook etc, however when we come to write tests for our component, we get the following error:

Test suite failed to run

Cannot find module 'react-compare-slider' from 'components/BeforeAfter/BeforeAfter.test.tsx'

Reproduction
The component

// components/BeforeAfter/index.tsx

import classNames from "classnames/bind";
import { useTranslation } from "next-i18next";
import { ReactCompareSlider } from "react-compare-slider";
import Icon, { IconName } from "@/components/Icon";
import breakpoints from "@/constants/breakpoints";
import CustomImage from "../CustomImage";
import styles from "./BeforeAfter.module.scss";

const cx = classNames.bind(styles);

export type BeforeAfterProps = {
  /**
   * The title text. Required.
   */
  title: string;
  /**
   * Optional body copy.
   */
  body?: string;
  /**
   * Optional boolean prop to show/hide the divider. Defaults to false.
   */
  divider?: boolean;
  /**
   * Image to use for the 'before' view.
   */
  beforeImage: { altText: string; src: string };
  /**
   * Image to use for the 'after' view.
   */
  afterImage: { altText: string; src: string };
};

const BeforeAfter = ({
  title,
  body,
  divider = false,
  beforeImage,
  afterImage,
}: BeforeAfterProps) => {
  const { t } = useTranslation("common");

  const imageOne = (
    <div className={cx("imageWrap")}>
      <CustomImage
        alt={beforeImage.altText}
        src={`${beforeImage.src}?io=transform:fit`}
        fill
        sizes={`(max-width: ${breakpoints.s}px) 100vw, (max-width: ${breakpoints.oversize}px) 50vw, 960px`} // TODO
      />
    </div>
  );

  const imageTwo = (
    <div className={cx("imageWrap")}>
      <CustomImage
        alt={afterImage.altText}
        src={`${afterImage.src}?io=transform:fit`}
        fill
        sizes={`(max-width: ${breakpoints.s}px) 100vw, (max-width: ${breakpoints.oversize}px) 50vw, 960px`} // TODO
      />
    </div>
  );

  const CustomHandle: React.FC = () => {
    return (
      <div className={cx("customHandle")}>
        <div className={cx("line")}></div>
        <div className={cx("handle")}>
          <Icon name={IconName.DOUBLE_CHEVRON} />
        </div>
        <div className={cx("line")}></div>
      </div>
    );
  };

  return (
    <section className="u-sectionPadding-h">
      <div className={cx("contentWrap", divider && "divider")}>
        <div className={cx("textWrap")}>
          <h4 className={cx("title", "u-strong")}>{title}</h4>
          {body && <p className={cx("body")}>{body}</p>}
        </div>
        <div className={cx("compareImagesWrap")}>
          <ReactCompareSlider
            itemOne={imageOne}
            itemTwo={imageTwo}
            handle={<CustomHandle />}
          />

          <div className={cx("labels")}>
            <h5 className="h6 u-strong">{t("before-after.before")}</h5>
            <h5 className="h6 u-strong">{t("before-after.after")}</h5>
          </div>
        </div>
      </div>
    </section>
  );
};

export default BeforeAfter;

Failing test

import { render, screen } from "@testing-library/react";
import BeforeAfter from ".";

jest.mock("next-i18next", () => ({
  useTranslation: () => ({
    t: (key: string) => key,
  }),
}));

describe("BeforeAfter component", () => {
  // Basic render test
  it("renders correctly", () => {
    render(
      <BeforeAfter
        title="Test Title"
        beforeImage={{ altText: "Before Image", src: "before.jpg" }}
        afterImage={{ altText: "After Image", src: "after.jpg" }}
      />,
    );
    expect(screen.getByText("Test Title")).toBeInTheDocument();
    expect(screen.getByText("before-after.before")).toBeInTheDocument();
    expect(screen.getByText("before-after.after")).toBeInTheDocument();
  });
});

Expected Behaviour
A test using a component that utilises react-compare-slider should run without errors, using version 3.X of the library.

Actual Behaviour
When running version 3.X (tested 3.1.0 and 3.0.1), the above error occurs when running a jest test for a component that uses the library.

Downgrading to version 2.2.0 resolves the issue.

Thanks for opening this @stevebutler2210. v3 dropped the CommonJS exports and now only provides ES modules so the issue is probably to do with that.

Are you using any build system on top of Jest like typescript-eslint, custom Webpack setup, etc?

Hey @nerdyman, thanks for the speedy response. We're using Next JS, so it's using webpack, but we've not really done much customisation of the setup etc

Thanks @stevebutler2210. I'll spin up a Next project and see if I can repro. Do you know which node and next versions you're using?

Thanks @nerdyman, that would be great! I'm running on Next 14.1.0 and Node 20.11.1

Good news is I can repro this but I'm not sure how to resolve it yet. I'd rather not start publishing CommonJS modules again just to appease Jest but ESM support isn't there yet jestjs/jest#9430.

I'll try some stuff out and if all else fails I'll add CJS modules back to the package.

This should be resolved in v4. I need to do testing on other devices before doing a final release but there is a pre-release with the CJS modules published.

It can be installed by running:

pnpm i react-compare-slider@beta
# Or
yarn add react-compare-slider@beta
# Or
npm i react-compare-slider@beta