0

I have been trying to figure this out. I had a lot of issues trying to setup Jest in my react project. Below are my configurations:

webpack.config.js

const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ip = require('ip');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js',
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        loader: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
          'sass-loader',
        ],
      },
      {
        test: /\.(jpg|jpeg|png|svg)$/,
        loader: {
          loader: 'file-loader',
          options: {
            outputPath: 'images',
            name: '[name].[ext]',
          },
        },
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.scss'],
    alias: {
      sass: path.resolve(__dirname, 'src/shared/sass'),
      src: path.resolve(__dirname, 'src'),
    },
  },
  plugins: [
    new CopyWebpackPlugin([{ from: path.resolve('public') }]),
    new MiniCssExtractPlugin({ filename: 'css/main.css' }),
  ],
  devServer: {
    open: true,
    port: 3200,
    host: ip.address(),
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, 'dist'),
    stats: 'errors-only',
  },
  stats: 'errors-only',
};

package.json

{
  "name": "AdminPortfolio",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "@nivo/line": "^0.62.0",
    "@nivo/stream": "^0.62.0",
    "core-js": "^3.6.5",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-redux": "^7.2.1",
    "react-router-dom": "^5.2.0",
    "redux": "^4.0.5",
    "regenerator-runtime": "^0.13.7"
  },
  "devDependencies": {
    "@babel/core": "^7.11.0",
    "@babel/preset-env": "^7.11.0",
    "@babel/preset-react": "^7.10.4",
    "babel-jest": "^26.2.2",
    "babel-loader": "^8.1.0",
    "copy-webpack-plugin": "5.1.1",
    "css-loader": "^4.2.0",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.2",
    "file-loader": "^6.0.0",
    "identity-obj-proxy": "^3.0.0",
    "ip": "^1.1.5",
    "jest": "^26.2.2",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.14.1",
    "sass-jest": "^0.1.7",
    "sass-loader": "^9.0.2",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "scripts": {
    "start": "webpack-dev-server",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage --colors"
  }
}

jest.config.js

module.exports = {
  // Automatically clear mock calls and instances between every test
  clearMocks: true,

  // An array of glob patterns indicating a set of files for which coverage information should be collected
  collectCoverageFrom: ['src/**/*.{js,jsx,mjs}'],

  // The directory where Jest should output its coverage files
  coverageDirectory: 'coverage',

  // An array of file extensions your modules use
  moduleFileExtensions: ['js', 'json', 'jsx', 'scss'],

  moduleNameMapper: {
    '^sass(.*)$': '<rootDir>/src/shared/sass/$1',
  },

  transform: {
    '^.+\\.scss$': 'sass-jest',
    '^.+\\.(js|jsx)$': 'babel-jest',
  },

  // The paths to modules that run some code to configure or set up the testing environment before each test
  setupFiles: ['<rootDir>/enzyme.config.js'],

  // The test environment that will be used for testing
  testEnvironment: 'jsdom',

  // The glob patterns Jest uses to detect test files
  testMatch: ['**/__tests__/**/*.js?(x)', '**/?(*.)+(spec|test).js?(x)'],

  // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
  testPathIgnorePatterns: ['\\\\node_modules\\\\'],

  // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
  testURL: 'http://localhost',

  // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
  transformIgnorePatterns: ['<rootDir>/node_modules/'],

  // Indicates whether each individual test should be reported during the run
  verbose: false,
};

Below is the component i am testing.

import React from 'react';
import classes from './style';

const PageHeader = ({ header }) => {
  return <div className={classes.header}>{header}</div>;
};

export default PageHeader;

Below is the style.scss file

@import 'sass/theme';
@import 'sass/mix';

.header {
  @include withTheme {
    color: useValue('c08');
  }
  font-size: pxtorem(20);
  font-weight: 400;
  padding-bottom: 35px;
}

And this is my test file

import React from 'react';
import { shallow } from 'enzyme';
import PageHeader from './index';

const setup = () => {
  const props = { header: 'Test' };
  const wrapper = shallow(<PageHeader />);
  return { props, wrapper };
};

describe('PageHeader Test Suite', () => {
  it('Should have a div', () => {
    const { wrapper } = setup();
    expect(wrapper.find('div').exists()).toBe(true);
  });
});

When i run the test i get the following error

$ jest FAIL  src/shared/components/PageHeader/PageHeader.test.js  ● Test suite failed to run
    Import error in:    /Users/raj.prem/Desktop/Random/AdminPortfolio    The import "sass/theme" could not be resolved. Searched paths:     - /Users/raj.prem/Desktop/Random/AdminPortfolio/sass/_theme.scss
     - /Users/raj.prem/Desktop/Random/AdminPortfolio/sass/theme.scss     - /Users/raj.prem/Desktop/Random/sass/_theme.scss
     - /Users/raj.prem/Desktop/Random/sass/theme.scss     - /Users/raj.prem/Desktop/Random/AdminPortfolio/src/shared/components/PageHe
ader/sass/_theme.scss     - /Users/raj.prem/Desktop/Random/AdminPortfolio/src/shared/components/PageHe
ader/sass/theme.scss     - /Users/raj.prem/Desktop/Random/AdminPortfolio/node_modules/sass-jest/sass/_theme.scss     - /Users/raj.prem/Desktop/Random/AdminPortfolio/node_modules/sass-jest/sass/
theme.scss

      at Importer.pathLookupError (node_modules/sass-thematic/lib/ast.js:256:12)
      at Importer.resolveSync (node_modules/sass-thematic/lib/ast.js:237:16)      at importFor (node_modules/sass-thematic/lib/ast.js:317:34)
      at File.parse (node_modules/sass-thematic/lib/ast.js:385:11)
      at Importer.runSync (node_modules/sass-thematic/lib/ast.js:155:17)      at Object.parseSync (node_modules/sass-thematic/lib/ast.js:407:31)      at Function.Thematic.parseASTSync (node_modules/sass-thematic/index.js:13:14)
      at Object.process (node_modules/sass-jest/transform-sass.js:226:25)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/Sc
riptTransformer.js:463:35)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform
/build/ScriptTransformer.js:568:40)

Test Suites: 1 failed, 1 totalTests:       0 totalSnapshots:   0 total
Time:        1.306 s
Ran all test suites.
error Command failed with exit code 1.

It seems like the alias used in the scss file cannot be resolved. Can somebody guide me in setting this up to work? The test works just find when i remove the styling from the div and remove the import statement of the style.scss

Thank you.

EDIT: Or is there a way to ignore the scss since im not testing any styles. The styles are just used in the components.

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Prem Raj
  • 849
  • 4
  • 15

1 Answers1

0

The way I've got to solve this problem importing sass|scss files was using "identity-obj-proxy", as mentioned in this question.

$ npm i -D identity-obj-proxy

// package.json
{
  (...)
  "scripts": {
    "test": "jest",
    "start": "styleguidist server"
  },
  "jest": {
    "moduleNameMapper": {
      "\\.(css|sass)$": "identity-obj-proxy"
    }
  },
 (...)
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Eduardo Oliveira
  • 395
  • 2
  • 18