Swiper 8 and jest
Asked Answered
D

3

4

Swiper 8 and Jest (support ESM) Must use import to load ES Module enter image description here enter image description here

How we can solve if I need to keep swiper 8 (without downgrade)

Drillmaster answered 6/5, 2022 at 12:35 Comment(2)
Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.Alidia
I have updated my answer below with the solution to our problem. Feel free to use it as is. :)Prurient
D
5

In case someone runs into this same issue but is using NextJs 12.2, next/jest and Jest 28 the answer is a variation from Francisco Barros' answer.

// jest.config.js
const nextJest = require('next/jest')

const createJestConfig = nextJest({
  // Path to Next.js app to load next.config.js
  dir: './'
})

/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig = {
  /**
   * Custom config goes here, I am not adding it to keep this example simple.
   * See next/jest examples for more information.
   */
 }

module.exports = async () => ({
  /**
   * Using ...(await createJestConfig(customJestConfig)()) to override transformIgnorePatterns
   * provided byt next/jest.
   * 
   * @link https://github.com/vercel/next.js/issues/36077#issuecomment-1096635363
   */
  ...(await createJestConfig(customJestConfig)()),
  /**
   * Swiper uses ECMAScript Modules (ESM) and Jest provides some experimental support for it
   * but "node_modules" are not transpiled by next/jest yet.
   *
   * @link https://github.com/vercel/next.js/issues/36077#issuecomment-1096698456
   * @link https://jestjs.io/docs/ecmascript-modules
   */
  transformIgnorePatterns: [
    'node_modules/(?!(swiper|ssr-window|dom7)/)',
  ]
})

The transformIgnorePatterns on jest.config.js prevents the Swiper files from being transformed by Jest but it affects the CSS files that are provided by this package.

Mocking these CSS files is the solution with the smallest configuration. In my case, it didn't matter much about having access to these CSS files while testing but there are other approaches if these files are relevant to you.

// jest.setup.js
import "@testing-library/jest-dom/extend-expect";

jest.mock("swiper/css", jest.fn());

export {};

I created a repository for a full reference of the necessary setup. https://github.com/markcnunes/with-jest-and-esm

Have in mind this setup might have to change for future Next.js / next/js versions but just sharing this approach in case this is useful for other people using this same setup.

Deuterogamy answered 10/7, 2022 at 6:52 Comment(0)
P
2

I have the same issue and still searching for a solution; I believe what the OP is asking is how can we transform swiper/react into a CJS module on the JEST pipeline.

  • Since using ESM Experimental in jest is not a good option...
  • Downgrading to v6 is not an option;
  • Any code that imports Swiper v8 fails in JEST because Swiper 8 only exports ESM;

A few days have passed since my original response. In the mean time I have found a solution that I have been using to effectively use Swiper v8 while still being able to test components that depend on it using jest.

The trick is to map the ESM imports to actual JavaScript and CSS files exported by Swiper, which can then be processed by babel and transpiled into CJS.

Create a file

// ./mocks/misc/swiper.js

module.exports = {
  // Rewrite Swiper ESM imports as paths (allows them to be transformed w/o errors)
  moduleNameMapper: {
    "swiper/react": "<rootDir>/node_modules/swiper/react/swiper-react.js",
    "swiper/css": "<rootDir>/node_modules/swiper/swiper.min.css",
    "swiper/css/bundle": "<rootDir>/node_modules/swiper/swiper-bundle.min.css",
    "swiper/css/autoplay": "<rootDir>/node_modules/swiper/modules/autoplay/autoplay.min.css",
    "swiper/css/free-mode": "<rootDir>/node_modules/swiper/modules/autoplay/free-mode.min.css",
    "swiper/css/navigation": "<rootDir>/node_modules/swiper/modules/autoplay/navigation.min.css",
    "swiper/css/pagination": "<rootDir>/node_modules/swiper/modules/autoplay/pagination.min.css"
  },
  // Allow Swiper js and css mapped modules to be imported in test files
  transform: {
    "^.+\\.(js|jsx|ts|tsx)$": ["babel-jest", { presets: ["next/babel"] }],
    "^.+\\.(css)$": "<rootDir>/jest.transform.js"
  },
  // Do not transform any node_modules to CJS except for Swiper and Friends
  transformIgnorePatterns: ["/node_modules/(?!swiper|swiper/react|ssr-window|dom7)"]
}

Create another file in the root of your repository

// jest.transform.js
"use strict"

const path = require("path")

// Requried to fix Swiper CSS imports during jest executions, it transforms imports into filenames
module.exports = {
  process: (_src, filename) => `module.exports = ${JSON.stringify(path.basename(filename))};`
}

Finally in your jest configuration use the things you created

// jest.config.js

const swiperMocks = require("./mocks/misc/swipper");

module.exports = {
 ...yourConfigurations
 moduleNameMapper: {
   ...yourOtherModuleNameMappers,
   ...swiperMocks.moduleNameMapper,
 },
 transform: {
   ...yourOtherTransforms
   ...swiperMocks.transform,
  },
  transformIgnorePatterns: [
    ...yourOtherTransformsIgnorePatterns
    ...swiperMocks.transformIgnorePatterns,
  ],
}

Prurient answered 23/6, 2022 at 11:34 Comment(0)
O
0

i would improve Francisco's answer a bit:

instead of putting all the css modules in the array, you can put just these two lines:

'swiper/css': '<rootDir>/node_modules/swiper/swiper.min.css',
'swiper/css/*': '<rootDir>/node_modules/swiper/modules/*/swiper.min.css',
Overbear answered 16/5, 2023 at 15:33 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewBusty

© 2022 - 2024 — McMap. All rights reserved.