Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional resolver is not working on jest #141

Closed
evrenesat opened this issue Nov 15, 2017 · 13 comments
Closed

Additional resolver is not working on jest #141

evrenesat opened this issue Nov 15, 2017 · 13 comments

Comments

@evrenesat
Copy link

Hello,

Thank you for this project. I'm using the following config override to be able to import packages outside of project folder. But jest could not find the package that I'm loading from that path. Is that normal, should I also provide the same resolver to jest via resolver config?

react@15.6.1
react-app-rewired@1.3.5

config-overrides.js

const path = require('path');
const fs = require('fs');

const appDirectory = fs.realpathSync(process.cwd());
const resolveRelativePath = relativePath => path.resolve(appDirectory, relativePath);
const extlibPath = resolveRelativePath('../../../../extlib/js');
const extlibBabelConfig = {
  test: /\.(js|jsx)$/,
  include: extlibPath,
  loader: require.resolve('babel-loader'),
  options: {
    babelrc: false,
    presets: [require.resolve('babel-preset-react-app')],
    compact: true
  }
};
module.exports = function override (config, env) {
  // allow importing from outside of app/src folder, ModuleScopePlugin prevents this.
  delete config.resolve.plugins.ModuleScopePlugin;
  // add extlib/js path to resolve path list,
  // so we can import from extlib without relative path dots (../../..), just like node_modules
  config.resolve.modules.push(extlibPath);
  // treat the modules that placed under extlib as ES6
  config.module.rules.push(extlibBabelConfig);
  return config;
};

Error:

 FAIL  src\containers\App.test.js
  ● Test suite failed to run

    Cannot find module 'number-format/NumberFormat' from 'Parameter.js'

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:179:17)
      at Object.<anonymous> (src/components/Parameter.js:3:21)
@timarney
Copy link
Owner

I won't have time to dig into this but did you try providing the config to Jest?

  webpack: function (config, env) {
    return config;
  },
  jest: function (config) {
    return config;
  }

See

https://github.com/timarney/react-app-rewired/blob/master/packages/react-app-rewired/config-overrides.js

@timarney
Copy link
Owner

Going to close this as it's not bug related.

This has been opened to cover Jest related notes #146. If you do happen to figure it out might be worth noting.

@stephenkoo
Copy link

stephenkoo commented Jun 14, 2018

@timarney I'm having the same difficulty finding a way to add require.resolve('babel-loader') into Jest config, since the jest config object is structured differently from the webpack config object.

For context, I'm following https://www.youtube.com/watch?v=gt8x6uODvEQ and have successfully run babel-loader in the webpack part of the config-override.js, but Jest (due to the config being different) doesn't like this:


module.exports = {
  webpack: function override(config, env) {
    config.module.rules[1].oneOf[2].use.unshift({
      loader: require.resolve('babel-loader'),
    });

    return config;
  },
  jest: function override(config) {
      config.module.rules[1].oneOf[2].use.unshift({
        loader: require.resolve('babel-loader'),
      });

    return config;
  },
};

This results in babel-plugin-emotion not being loaded into Jest tests. When running test, this results:

You're trying to use the styled shorthand without babel-plugin-emotion.
    Please install and setup babel-plugin-emotion or use the function call syntax(`styled('div')` instead of `styled.div`)

What's the right way of doing this? (For a Typescript CRA specifically)

@stephenkoo
Copy link

stephenkoo commented Jun 14, 2018

@timarney Yes, I've attempted using react-app-rewire-emotion with TypeScript CRA. Using that, both yarn start & yarn test both show the missing babel-plugin-emotion error.

How can I use getBabelLoader() in the context of the Jest test script config-override.js?

To elaborate on why react-app-rewire-emotion doesn’t work, all it does it uses injectBabelPlugin to add plugins: [emotion] to a loader which is not what's needed (that can already be done in the .babelrc.) What's needed is to modify the config object to use a babel-loader right before the ts-loader, i.e. convert module.rules[2].oneOf[2] from:

{  
  "test":{  

  },
  "include":"/Users/stephenkoo/code/src/gitlab.com/stephenkoo/kanso/src",
  "use":[  
      {  
        "loader":"/Users/stephenkoo/code/src/gitlab.com/stephenkoo/kanso/node_modules/ts-loader/index.js",
        "options":{  
            "transpileOnly":true
        }
      }
  ]
},

to

{  
  "test":{  

  },
  "include":"/Users/stephenkoo/code/src/gitlab.com/stephenkoo/kanso/src",
  "use":[  
+      {  
+        "loader":"/Users/stephenkoo/code/src/gitlab.com/stephenkoo/kanso/node_modules/babel-loader/lib/index.js"
+      },
      {  
        "loader":"/Users/stephenkoo/code/src/gitlab.com/stephenkoo/kanso/node_modules/ts-loader/index.js",
        "options":{  
            "transpileOnly":true
        }
      }
  ]
},

@dawnmist
Copy link
Collaborator

dawnmist commented Jun 14, 2018

@stephenkoo Jest doesn't use Webpack at all, so trying to modify Webpack rules for it will not work. The config it is editing is a Jest Config. There are no loaders to modify for the Jest config, as it doesn't use Webpack loaders. Assuming that you've used create-react-app-typescript, the yarn test script will invoke jest using ts-jest to transpile.

Setting up your jest function is documented here.

The default Jest config given to your config-overrides jest function permits you to specify babel plugins through either .babelrc or in a babel section in your package.json file using the normal babel configuration options. If all you need to do for the Jest testing is to add babel plugins, you don't even need to specify the jest function - just create your babel configuration and it'll be automatically used.

As an example, I have a project (also in typescript) where I use dynamic imports for code splitting. Node doesn't understand their syntax by default, so I need to use babel-plugin-dynamic-import-node. I wanted to restrict this to the testing environment only, as webpack's loaders handle it automatically. I also needed to transform some modules from es2015 to commonjs so that node would understand them. To do this, all that was required was to add the following section to my package.json file:

{
  ...the rest of your package.json file...,
  "babel": {
    "env": {
      "test": {
        "plugins": [
          "transform-es2015-modules-commonjs",
          "dynamic-import-node"
        ]
      }
    }
  }
}

@stephenkoo
Copy link

stephenkoo commented Jun 14, 2018

@dawnmist Thanks - I gave it a shot, but it's not working for babel-plugin-emotion (Same errors.)
What I did:

  1. Delete .babelrc
  2. Delete configure-override.json
  3. Add this to the end of package.json as per your example + babel-plugin-emotion documentation:
  "babel": {
    "env": {
      "production": {
        "plugins": [["emotion", { "hoist": true }]]
      },
      "development": {
        "plugins": [["emotion",  { "sourceMap": true, "autoLabel": true }]]
      },
      "test": {
        "plugins": [["emotion",  { "hoist": true }]]
      }
    }
  }

Result: Both yarn start & yarn test result in error not recognizing babel-plugin-emotion being installed.

Here's my full package.json:

{
  "lint-staged": {
    "*.{ts,tsx}": [
      "stylelint --fix",
      "prettier --config .prettierrc --write",
      "tslint --fix'",
      "yarn run test:staged",
      "git add"
    ],
    "*.{json,md}": [
      "prettier --config .prettierrc --write",
      "git add"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "scripts": {
    "start": "react-app-rewired start --scripts-version react-scripts-ts",
    "build": "react-app-rewired build --scripts-version react-scripts-ts",
    "test": "react-app-rewired test --scripts-version react-scripts-ts --env=jsdom",
    "test:staged": "cross-env CI=true react-app-rewired test --scripts-version react-scripts-ts --env=jsdom --findRelatedTests",
    "eject": "react-app-rewired --scripts-version react-scripts-ts eject",
    "lint:ts": "tslint 'src/**/*.{ts,tsx}'",
    "lint:styles": "stylelint 'src/***/*.{ts,tsx}'"
  },
  "dependencies": {
    "babel-loader": "^7.1.4",
    "babel-plugin-emotion": "^9.2.0",
    "babel-preset-env": "^1.7.0",
    "emotion": "^9.2.3",
    "react": "^16.4.0",
    "react-app-rewired": "^1.5.2",
    "react-dom": "^16.4.0",
    "react-emotion": "^9.2.3",
    "react-scripts-ts": "2.16.0"
  },
  "devDependencies": {
    "@types/jest": "^23.0.2",
    "@types/node": "^10.3.2",
    "@types/react": "^16.3.17",
    "@types/react-dom": "^16.0.6",
    "cross-env": "^5.2.0",
    "husky": "^1.0.0-rc.8",
    "lint-staged": "^7.2.0",
    "prettier": "^1.13.5",
    "stylelint": "^9.2.1",
    "stylelint-config-standard": "^18.2.0",
    "stylelint-config-styled-components": "^0.1.1",
    "stylelint-processor-styled-components": "^1.3.1",
    "typescript": "^2.9.1"
  },
  "babel": {
    "env": {
      "production": {
        "plugins": [["emotion", { "hoist": true }]]
      },
      "development": {
        "plugins": [["emotion",  { "sourceMap": true, "autoLabel": true }]]
      },
      "test": {
        "plugins": [["emotion",  { "hoist": true }]]
      }
    }
  }
}

@dawnmist
Copy link
Collaborator

dawnmist commented Jun 14, 2018

@stephenkoo Have you got an example repo that I can take a look at? (And what I had said only applied to yarn test - yarn start does use Webpack and needs the other method of specifying babel plugins).

@stephenkoo
Copy link

stephenkoo commented Jun 14, 2018

@dawnmist Definitely! https://gitlab.com/stephenkoo/kanso/tree/custom-setup

Thanks for having a look.

@dawnmist
Copy link
Collaborator

@stephenkoo I'm still tracing through what ts-jest/babel are doing with the test, but I found this bug report while looking up details about babel-plugin-emotion. I suspect that it may be related, but simply changing the module type to compile to doesn't fix it. Their sample repo may help though, as they have a "working" and "not working" example to trace through.

@dawnmist
Copy link
Collaborator

@stephenkoo It looks like there is actually a known incompatibility between ts-jest and emotion. When the ts source is transpiled prior to running babel on it, it loses the information that the babel-plugin-emotion needs for it to be able to do its job. Take a look here: kulshekhar/ts-jest#480

@dawnmist
Copy link
Collaborator

dawnmist commented Jun 14, 2018

@stephenkoo This syntax in App.tsx works with no other changes to your sample project:

const StyledDiv = styled('div')`
  color: pink;
  flex: 1;
`;

Not sure whether you're happy to switch to using it, but it is a relatively minor change (from styled.div to styled('div')) that can save you a lot of headaches. If I understand what I've read in the last few hours, it means that it's not having to rely on the babel plugin at all.

@stephenkoo
Copy link

@dawnmist Ah, yes - thanks for finding the root cause of the issue! I thought it must've been me not setting rewired up properly.

You’re right - babel-plugin-emotion is not necessary for emotion to work, but it provides optimization benefits that I'd rather not do without - the syntax I used was just to test if babel-plugin-emotion works with Create React App & TypeScript using rewired.

Sadly it looks like I'll have to choose either TypeScript or the optimisation benefits of the emotion plugin due to the issue you linked to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants