asmyshlyaev177/react-horizontal-scrolling-menu

[BUG] Cannot be imported in Jest with Next.js

xian0831 opened this issue · 8 comments

Describe the bug

@asmyshlyaev177 Thanks for building this library. I would like to report an issue I'm facing related to testing components that leverage the react-horizontal-scrolling-menu. I'm able to build the app fine, it is just not working with Jest unit test.

To Reproduce
There is not issue when using the library so there is nothing to reproduce.

I suspect the issue might have something to do with the Jest transform.This is the config I have.

    // A map from regular expressions to paths to transformers
    transform: {
        '^.+\\.(t|j)sx?$': [
            'babel-jest',
            {
                presets: ['next/babel'],
                plugins: [
                    'dynamic-import-node',
                    [
                        'babel-plugin-styled-components',
                        {
                            displayName: true,
                            preprocess: false,
                            fileName: false,
                        },
                    ],
                ],
            },
        ],
        '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2|svg)$':
            'jest-transform-stub',
    },

When I run the test, this is what I get SyntaxError: Cannot use import statement outside a module

image

Expected behavior
Successfully rendering by Jest using jsdom

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • Package Version: 4.1.0
  • Platform: Next.js 12.1.0
  • Assertion Lib: Jest + React Testing Library

Additional context
Someone else had anther import issue. I suspect it is somewhat related to this issue. However, I can't confirm that. Again, thanks for building the library.

@xian0831 Have you fixed this issue?

I have resolved the issue.
Just add to jest.config.js

  moduleNameMapper: {
    '^react-horizontal-scrolling-menu$': 'react-horizontal-scrolling-menu/dist/index.cjs',
  },

@andrey-shostik Sorry for getting back on this super late. I'm still having issue with your approach. However, if I switch from babel-jest to ts-jest. It solve the issue for this package, but other packages will failed for the same SyntaxError: Cannot use import statement outside a module error. Do you use ts-jest?

@xian0831 No, I don't use ts-jest
Babelrc

  const presets = [
    '@babel/preset-env',
    isTestEnv && 'next/babel', // Note: Ships with babel-plugin-transform-react-remove-prop-types
  ].filter(Boolean);
const plugins = [
   'module-resolver',
   {
     root: ['./'],
     extensions: ['.js', '.jsx', '.ts', '.tsx'],
   },
 ],
];

I tested it with NextJs v14.0.1. This is really messed up, it depends on NextJS version, library, your setup and phase of the moon.
I don't recommend testing complex browser related behavior with Jest, use Cypress or Playwright for that. Because jsdom lack browsers APIs(like IntersectionObjerver), and you will end up testing Jest mocks and not your code.

Steps:

1. Install testing library and deps npm i -D @testing-library/jest-dom @testing-library/react @testing-library/user-event jest-environment-jsdom

2. Create jest.config.ts file with

import type { Config } from 'jest'
import nextJest from 'next/jest.js'

const createJestConfig = nextJest({
  dir: './',
})

const config: Config = {
  coverageProvider: 'v8',
  // NOTE: important
  testEnvironment: 'jest-environment-jsdom', // or 'jsdom'
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}

export default createJestConfig(config)

3. Create jest.setup.js file with:

import '@testing-library/jest-dom'

// // NOTE: Mock IntersectionObserver
class IntersectionObserver {
  observe = jest.fn()
  disconnect = jest.fn()
  unobserve = jest.fn()
}

Object.defineProperty(window, 'IntersectionObserver', {
  writable: true,
  configurable: true,
  value: IntersectionObserver,
})

Object.defineProperty(global, 'IntersectionObserver', {
  writable: true,
  configurable: true,
  value: IntersectionObserver,
})

5. Create test file:

import React from 'react'
import { render } from '@testing-library/react';

import { App } from './page'

describe("Smoke test", () => {
  test('should render without errors', () => {
    const {  container } = render(<App />)

    expect(container).toBeTruthy()
  })
})

6. Add test script to package.json: "test": "jest", and run it npm run test