My Entire code:
Component type: (ProductGallery.types.ts)
type productGalleryType = {
productImages: string[];
};
export default productGalleryType;
Component: (ProductGallery.tsx)
import React, { useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import SwiperCore, { Thumbs } from 'swiper';
import productGalleryType from '../../@types/ProductGallery.types';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/thumbs';
const ProductGallery: React.FC<productGalleryType> = ({
productImages,
}: productGalleryType) => {
const [activeThumb, setActiveThumb] = useState<SwiperCore>();
return (
<>
<Swiper
loop={true}
spaceBetween={10}
modules={[Thumbs]}
grabCursor={true}
thumbs={{
swiper: activeThumb && !activeThumb.destroyed ? activeThumb : null,
}}
className="h-308 w-294 rounded-sm"
>
{productImages &&
productImages.map((item, index) => (
<SwiperSlide key={index} className="relative overflow-hidden">
<img
src={item}
alt="product gallery image"
className="m-0 h-full w-full object-cover object-center p-0"
/>
</SwiperSlide>
))}
</Swiper>
<Swiper
onSwiper={setActiveThumb}
loop={true}
spaceBetween={10}
slidesPerView={4}
modules={[Thumbs]}
className="mt-52 w-[338px]"
>
{productImages &&
productImages.map((item, index) => (
<SwiperSlide key={index} className="!mx-10 !h-66 !w-66 rounded-xxs">
<img
src={item}
alt="product gallery thumbnail"
className="m-0 h-full w-full rounded-xxs object-cover object-center p-0"
/>
</SwiperSlide>
))}
</Swiper>
</>
);
};
export default ProductGallery;
Story: (ProductGallery.stories.tsx)
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import ProductGallery from './ProductGallery';
const productImages = [
'https://dummyimage.com/1000x400/070be6/fff.png',
'https://dummyimage.com/900x900/bd09e6/fff.png',
'https://dummyimage.com/600x600/070be6/fff.png',
'https://dummyimage.com/1600x1400/ffaadd/fff.png',
'https://dummyimage.com/500x1000/ff0000/fff.png',
];
export default {
title: 'ProductGallery',
Component: ProductGallery,
argTypes: {},
} as ComponentMeta<typeof ProductGallery>;
const Template: ComponentStory<typeof ProductGallery> = (args) => (
<ProductGallery {...args} />
);
export const GalleryWithThumbnails = Template.bind({});
GalleryWithThumbnails.args = {
productImages: productImages,
};
Test: (ProductGallery.test.tsx)
(Causing Problem here)
import { render, screen } from '@testing-library/react';
import ProductGallery from './ProductGallery';
const productImages = [
'https://dummyimage.com/1000x400/070be6/fff.png',
'https://dummyimage.com/900x900/bd09e6/fff.png',
'https://dummyimage.com/600x600/070be6/fff.png',
];
describe('ProductGallery', () => {
it('Renders Primary Card', () => {
render(<ProductGallery productImages={productImages} />);
const imgThumbnailElements = screen.findAllByAltText(
'product gallery thumbnail',
);
expect(imgThumbnailElements).toHaveLength(3);
});
});
Package.JSON:
{
"name": "groceries-plus",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint:prettier": "prettier -c '{components,pages,cypress,styles}/**/*.{js,ts,tsx,jsx,css,json}'",
"lint:fix:prettier": "prettier --write '{components,pages,cypress,styles}/**/*.{js,ts,tsx,jsx,css,json}'",
"lint:eslint": "eslint",
"lint:fix:eslint": "eslint --fix",
"lint": "concurrently \"npm:lint:*(!fix)\"",
"test": "concurrently \"npm:test:*(!run)\"",
"test:rtl": "jest --coverage",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"generate-types": "contentful-typescript-codegen --output @types/generated/contentful.types.ts",
"test:cy:run": "cypress run",
"test:cy:start": "start-server-and-test dev 3000 test:cy:run"
},
"dependencies": {
"@reduxjs/toolkit": "^1.8.5",
"contentful": "^9.2.4",
"next": "12.3.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-redux": "^8.0.2",
"swiper": "^8.4.4"
},
"devDependencies": {
"@babel/core": "^7.19.1",
"@contentful/rich-text-types": "^15.13.2",
"@storybook/addon-actions": "^6.5.12",
"@storybook/addon-essentials": "^6.5.12",
"@storybook/addon-interactions": "^6.5.12",
"@storybook/addon-links": "^6.5.12",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.5.12",
"@storybook/cli": "^6.5.12",
"@storybook/manager-webpack5": "^6.5.12",
"@storybook/react": "^6.5.12",
"@storybook/testing-library": "^0.0.13",
"@tailwindcss/typography": "^0.5.7",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "18.7.18",
"@types/react": "18.0.20",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"autoprefixer": "^10.4.11",
"babel-loader": "^8.2.5",
"concurrently": "^7.4.0",
"contentful-management": "^10.15.1",
"contentful-typescript-codegen": "^3.2.3",
"cypress": "^10.9.0",
"dotenv": "^16.0.2",
"eslint": "^8.0.1",
"eslint-config-next": "12.3.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^23.0.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.31.8",
"eslint-plugin-storybook": "^0.6.4",
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3",
"postcss": "^8.4.16",
"prettier": "^2.7.1",
"prettier-plugin-tailwindcss": "^0.1.13",
"start-server-and-test": "^1.14.0",
"tailwindcss": "^3.1.8",
"typescript": "4.8.3",
"webpack": "^5"
}
}
jest.config.js:
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
/** @type {import('jest').Config} */
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
};
module.exports = createJestConfig(customJestConfig);
The Component and story render fine.
While running the test I'm getting the following error:
Tried so far:
I've tried many things like, adding the transformIgnorePatterns option to jest.config.js but it didn’t fix the error.
transformIgnorePatterns: [
'/node_modules/(?![swiper/react/swiper-react.js])',
'/node_modules/(?![swiper/react/swiper.js])'
],
After some more debugging, I modified the test:rtl script to this in package.json:
"test:rtl": "jest --coverage --transformIgnorePatterns \"node_modules/(?!swiper)/\"",
I'm looking for a lifesaver here. Thanks in advance.
I don't think I got there in time to save your life but the best solution I found is to mock all the things related with Swiper, in your case:
jest.mock("swiper/react", () => ({
Swiper: ({ children }: { children: React.ReactElement }) => (
<div>{children}</div>
),
SwiperSlide: ({ children }: { children: React.ReactElement }) => (
<div>{children}</div>
),
useSwiper: () => ({
swiper: {
slideNext: () => {},
},
}),
}));
jest.mock("swiper", () => ({
default: jest.fn(),
Thumbs: jest.fn()
}));