Issue encountered while conducting tests with Jest and React Testing Library on a React component containing an SVG: the type is not recognized in React.jsx

In my Next.js 12.1.4 project, I am using Typescript, React Testing Library, and SVGR for importing icons like this:

import ChevronLeftIcon from './chevron-left.svg'

The issue arises when running a test on a component that includes an SVG import, leading to the following error:

console.error
    Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
    
    Check the render method of `Loader`.
        at Loader (.../src/components/atoms/Loader/Loader.tsx:11:36)
        at div
        at button
        at Button (.../src/components/atoms/buttons/Button/Button.tsx:19:5)

      15 |         }`}
      16 |     >
    > 17 |         <LoaderIcon />
         |                       ^
      18 |     </div>
      19 | )
      20 |

      at printWarning (node_modules/react/cjs/react-jsx-runtime.development.js:117:30)
      at error (node_modules/react/cjs/react-jsx-runtime.development.js:93:5)
      at jsxWithValidation (node_modules/react/cjs/react-jsx-runtime.development.js:1152:7)
      at Object.jsxWithValidationDynamic [as jsx] (node_modules/react/cjs/react-jsx-runtime.development.js:1209:12)
      at Loader (src/components/atoms/Loader/Loader.tsx:17:23)
      at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:14985:18)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17811:13)

My tests are executed with yarn test, specified in the following script within my package.json:

"test": "TZ=UTC ./node_modules/jest/bin/jest.js",

This is what I have configured in next.config.js for SVGR:

webpack(config) {
    config.module.rules.push({
        test: /\.svg$/,
        use: ['@svgr/webpack'],
    })

    return config
},

Here is my jest.config.js setup:

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

const customJestConfig = {
  moduleDirectories: ['node_modules', '<rootDir>/src/'],
  testEnvironment: 'jest-environment-jsdom',
  moduleNameMapper: {
    '\\.svg$': '<rootDir>/src/__mocks__/svgrMock.tsx',
  },
}

module.exports = createJestConfig(customJestConfig)

and src/__mocks__/svgrMock.tsx:

import React, { SVGProps } from 'react'

const SvgrMock = React.forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(
    (props, ref) => <svg ref={ref} {...props} />,
)

SvgrMock.displayName = 'SvgrMock'

export const ReactComponent = SvgrMock
export default SvgrMock

I also attempted to utilize jest-svg-transformer without significant improvement.

These are the versions of the libraries being used:

  • "next": "^12.1.4"
  • "react": "17.0.2"
  • "react-dom": "17.0.2"
  • "@svgr/webpack": "^5.5.0"
  • "@testing-library/jest-dom": "^5.16.4"
  • "@testing-library/react": "^12.1.4"
  • "@testing-library/user-event": "^14.0.4"
  • "jest": "^27.5.1"
  • "ts-jest": "^27.1.3"
  • "typescript": "4.4.4"

Your assistance is greatly appreciated :)

Answer №1

After some trial and error, I managed to resolve the issue by utilizing the Jest with Babel setup recommended in the documentation for Next.js, instead of relying on the next/jest plugin powered by the Rust compiler: https://nextjs.org/docs/testing#setting-up-jest-with-babel

I also created a custom jest transformer for handling svg files, named jestSvgTransformer.js:

const path = require('path')

module.exports = {
  process(src, filePath) {
    if (path.extname(filePath) !== '.svg') {
      return src
    }

    const name = `svg-${path.basename(filePath, '.svg')}`
      .split(/\W+/)
      .map((x) => `${x.charAt(0).toUpperCase()}${x.slice(1)}`)
      .join('')

    return `
const React = require('react');
function ${name}(props) {
  return React.createElement(
    'svg',
    Object.assign({}, props, {'data-file-name': ${name}.name})
  )
}
module.exports = ${name}
            `
  },
}

In my jest.config.js

  • within the moduleNameMapper: remove svg from the mapping
    '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp)$/i': '<rootDir>/<path to your mock files (e.g.) __mocks__>/fileMock.js',
  • in the transform section: include
    '^.+\\.svg$': '<rootDir>/<path to your mock files (e.g.) __mocks__>/jestSvgTransformer.js'
  • introduce
    moduleDirectories: ['node_modules', 'src'],
    to facilitate absolute imports

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using TypeScript to Add Items to a Sorted Set in Redis

When attempting to insert a value into a sorted set in Redis using TypeScript with code like client.ZADD('test', 10, 'test'), an error is thrown Error: Argument of type '["test", 10, "test"]' is not assigna ...

How should I properly initialize my numeric variable in Vue.js 3?

Encountering an issue with Vue 3 where the error message reads: Type 'null' is not assignable to type 'number'. The problematic code snippet looks like this: interface ComponentState { heroSelected: number; } export default define ...

Is Next.js the Ultimate Serverless Rendering Tool with Cloudflare Workers?

I am currently using Next.js version 9 and I am interested in utilizing Next's serverless deployment feature by integrating my application with Cloudflare Workers. According to the documentation for Next.js, all serverless functions created by Next f ...

An unfamiliar data type is provided as a number but is treated as a string that behaves like a number

Here is the code snippet in question: let myVar = unknown; myVar = 5; console.log((myVar as string) + 5); Upon running this code, it surprisingly outputs 10 instead of what I expected to be 55. Can someone help me understand why? ...

Tips for solving a deliberate circular dependency in an angular provider

If the existing injection token for this provider is available, I want to use it. Otherwise, I will use the specified provider. Below is the code snippet: providers: [ { provide: DesignerRecoveryComponentStore, useFacto ...

Automate the process of replacing imports in Jest automatically

Currently, I am in the process of setting up a testbench for a more intricate application. One challenge we are facing is that our app needs to call backend code which must be mocked to ensure the testbench runs efficiently. To address this issue, we utili ...

There was an issue serializing the `.product` data that was returned from `getStaticProps` in the "/prints/[name]" route in Next.js

My Strapi nextjs application has 2 categories of products. Everything works fine locally, but I encounter an error when trying to build: Error serializing .product returned from getStaticProps in "/prints/[name]". Reason: undefined cannot be se ...

Is it common practice to make an API request in Next.js?

Presently, my backend is in NodeJS (Express) and I am currently transitioning from create-react-app to NextJS on the frontend. Should I continue making API requests from NextJS to the Express server or should I consider moving the APIs to NextJS itself so ...

Is there a way to incorporate several select choices using specific HTML?

I am currently trying to dynamically populate a select tag with multiple option tags based on custom HTML content. While I understand how to insert dynamic content with ng-content, my challenge lies in separating the dynamic content and wrapping it in mat ...

Enhance a subject's behavior by overriding the .next method using a decorator

Currently, I am working on an Angular application where I have numerous Subjects, BehaviorSubjects, and ReplaySubjects as properties in various services. I am attempting to create a TypeScript decorator that can be added to some of these Subjects to enhanc ...

bundle.js encountered a TypeError when attempting to read a property that was undefined, specifically while trying to access the PriceIndexationDataControlStandard

In the midst of developing a React component using the Microsoft PCF Framework, I encountered a perplexing error seemingly out of the blue. While making changes in TypeScript without even executing any build commands, the rendering of my component suddenly ...

JavaScript heap running out of memory after upgrading from Angular 11 to versions 12, 13, or 14

I need assistance with resolving a JS heap out of memory issue that has been occurring when trying to start the local server ever since migrating from Angular 11 to Angular 12 (or 13 or 14, all versions tested with the same problem). This occurs during th ...

What is the syntax for utilizing cookies within the `getServerSideProps` function in Next.js?

I am struggling to pass the current language to an endpoint. Despite attempting to retrieve the language from a Cookie, I keep getting undefined within the getServerSideProps function. export async function getServerSideProps(context) { const lang = aw ...

The condition will be false if a number is present, even if it is zero

I am facing an issue with a class containing an optional field called startDateHour: export class Test { startDateHour?: number; // more fields, constructor etc. } I need to perform an action only if the startDateHour exists: if (test.startDateHour ...

Trouble with loading images when navigating to a new page with NextJS Link component

Explaining this issue thoroughly would require sharing my entire project, but here's a brief overview. I suspect the problem lies within using a combination of getInitialProps() and getStaticProps(). When navigating between pages using next/link, imag ...

Dealing with Errors in Angular 5 using Observables: Why Observable.throw isn't working

Can someone assist with resolving this issue? Error message: core.js:1542 ERROR TypeError: rxjs__WEBPACK_IMPORTED_MODULE_3__.Observable.throw is not a function Software versions: Angular CLI: 6.0.8 / rxjs 6.2.1 import { Injectable } from '@angular/ ...

"Create a separate function for the pipeable operator in RXJS for enhanced code

After working on some code, I came up with the following implementation this.form.valueChanges.pipe( take(1), map(val => // doSomething), exhaustMap(val => // someInner observable logic return of({someValue}) ) ).subscrib ...

Issue encountered while utilizing JQueryUI alongside TypeScript and the definition file from DefinitelyTyped

Currently, I'm attempting to incorporate JQueryUI with TypeScript by first installing JQueryUI using npm install jquery-ui-dist, and then installing JQuery with npm install jquery. Additionally, I have included the definition files from DefinitelyType ...

Unexpected Null Object Error in TypeScript Function

Hi there! I'm new to TypeScript and encountered an 'Object may be null' error in a function. The function is meant to add two LinkedLists together, each representing numbers (with each digit as its own node), and return a new LinkedList. Can ...

Problem of Repetitive Text in Yjs Collaborative Editing

Description: Currently, I am working on implementing collaborative editing functionality using Yjs for a script editor within my React application. While the collaborative editing feature works smoothly, I have come across an issue when multiple users are ...