2

A React Context provider imports style classes from a module.scss file. When executing this component a selected style class is loaded and passed as the className to child components.

import React, {createContext, ReactChild, useState} from 'react'
import themes from './ThemeProvider.module.scss'

type ThemeContext = {
  activeTheme: string
  changeTheme: (theme: string) => void
}

const validThemes = Object.keys(themes)
console.log(themes)
const defaultTheme = 'light'

const defaultThemeContext: ThemeContext = {
  activeTheme: defaultTheme,
  changeTheme: () => undefined
}

type ThemeProviderProps = {
  children: ReactChild
}

export const ThemeContext = createContext<ThemeContext>(defaultThemeContext)

export const ThemeProvider = ({children}: ThemeProviderProps): JSX.Element => {
  const [theme, setTheme] = useState(defaultThemeContext.activeTheme)

  const changeTheme = (themeName: string): void => {
    console.log('changing theme')
    console.log(themes[themeName])
    if (validThemes.includes(themeName)) {
      setTheme(themeName)
    } else {
      setTheme(defaultTheme)
    }
  }

  const themeContext = {
    activeTheme: theme,
    changeTheme: changeTheme
  }

  return (
    <ThemeContext.Provider value={themeContext}>
      <div className={themes[theme]} data-testid='theme-provider'>
        {children}
      </div>
    </ThemeContext.Provider>
  )
}

If changeTheme is invoked the following output is logged to the console.

{
    "dark": "x05Ym2JQjxImZ4atKmpS",
    "light": "hOdKKkIeHEdunEiPWlEL"
}

changing Theme
x05Ym2JQjxImZ4atKmpS

When trying to test this component in using testing-library using a custom renderer

/**
 * Custom renderer
 */
const ThemeConsumer = (): JSX.Element => {
  const {changeTheme, activeTheme} = useContext(ThemeContext)
  return (
    <div>
      <button
        data-testid='theme-consumer-btn'
        onClick={() => {
          console.log('CLICK!')
          changeTheme('dark')
        }}
      />
      <p>Theme:{activeTheme} </p>
    </div>
  )
}

And the following test

  test('changes theme', async () => {
    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>
    )

    const consumerBtn = (await screen.findByTestId(
      'theme-consumer-btn'
    )) as HTMLButtonElement

    await userEvent.click(consumerBtn)
    await waitFor(() => screen.getByText('Theme:dark'))
    screen.debug(undefined, Infinity)
  })

On execution of the test the CLICK! message from the custom renderer is logged as the same console.log statements when executed in a browser. Only, where the CSS style classes were expected i get an empty object.

{}

changing Theme
dark

Used Jest config is

/**
 * @jest-environment jsdom
 */

module.exports = {
  collectCoverageFrom: ['src/**/*.ts', 'src/**/*.tsx', '!src/**/*.test.*'],
  moduleNameMapper: {
    '\\.(scss)$': '<rootDir>/node_modules/jest-css-modules'
  },
  testEnvironment: 'jsdom',
  globals: {
    PRODUCTION: true
  },
  testMatch: ['**/?(*.)test.[tj]sx'],
  testURL: 'https://www.mijnmarkt.nl',
  coverageThreshold: {
    global: {
      lines: 100,
      statements: 100
    }
  }
}

Is there a configuration, module or any other change to be able to parse css-modules in Jest as when hosting it locally through a Webpack serve?

1 Answer 1

3

replacing the jest-css-modules moduleNameMapper with the following two jest transform configurations fixed the issue.

yarn add --dev babel-jest jest-css-modules-transform

and jest config

  transform: {
    '^.+\\.[jt]sx?$': 'babel-jest',
    '.+\\.(css|styl|less|sass|scss)$': 'jest-css-modules-transform'
  },
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.