Babel module-resolver not working with Mocha tests - javascript

I'm trying to run some React tests using Mocha. My react components have aliases via Babel's "babel-plugin-module-resolver": "^3.1.1",, they work, but they don't work when running tests.
Here is the error when running testes:
Error: Cannot find module 'Styles/dimensions'
Here are my .babelrc configs:
...
"plugins": [
[ "module-resolver",
{
"root": ["."],
"extensions": [".js", ".json", ".jsx", ".ts", ".tsx"],
"alias": {
"Styles": ["./app/react/styles"],
}
}
]
]
...
My mocha-setup.js file includes:
require('moment');
require('babel-plugin-module-resolver');
require('babel-polyfill');
require('babel-register')({
only: /(node_modules\/|\.test.js)/,
});
require('ts-node').register({
project: './app/tests/config/tsconfig.test.json',
});
require('./helpers');
require('./browser');
Here is my command used to run the tests:
cross-env NODE_PATH=./ NODE_ENV=test mocha 'app/react/**/*.test.{js,jsx}' --require ./app/tests/config/mocha-setup.js
Any ideas on how to get Mocha to compile those aliases? The test run file without the alias, but Mocha doesn't seem to be running the alias compilation before running the tests.

I've solved this problem by this code in .babelrc.js:
const module_resolver = [
"module-resolver",
{
extensions: [".js", ".jsx", ".es", ".es6", ".mjs"],
root: ["./"],
alias: {
"#store": "./src/store"
},
},
];
const presets = ()=>{
return [
"#babel/preset-env",
"#babel/preset-react"
]
}
const plugins = ()=>{
let base = [
["#babel/plugin-proposal-class-properties"],
["#babel/transform-runtime"]
];
if (process.env.NODE_ENV='test')
{
base.push(module_resolver);
}
return base;
}
let config = {
presets: presets(),
plugins: plugins()
};
module.exports = config;

Related

Cypress for Components Tests React configuration problem absolute path

the goal is to use Cypress for component testing and e2e testing mainly.
Install and configure all Cypress correctly, configure Cypress in the 'cypress open' script to open E2E related tests and configure the 'cypress open-ct' script for component tests, all settings work very well.
Problem
The project is already ready and I have absolute folders configuration, when I import a component from '~/components' I am accessing 'src/components', I am not able to make the proper settings to be able to access the absolute folders because when I run the cypress open script -ct doesn't seem to run 'file:preprocessor', where you need to run it to run the webpack where you have the absolute folder settings.
I tried several alternatives and this was the one that worked the best because when I run the 'cypress open' script cypress executes 'file:preprocessor' it applies the webpack settings and if I try to import a component using '~/component/InputDate' it works , however 'cypress open' is for E2E tests, I can't run unit tests through this script.
I can be wrong about the cypress open script not running component tests correctly but I'm looking for a solution to the big problem that is these absolute folders.
Attempts
I tried the tsconfig.json files configuration solution but I couldn't make it work because I use it in the jsconfig.json project, I tried to use tsconfig.json I used the 'tsconfig-paths' package and got no result.
cypress/plugins/index.js
const webpack = require('#cypress/webpack-preprocessor')
const injectDevServer = require('#cypress/react/plugins/react-scripts')
module.exports = (on, config) => {
const options = {
webpackOptions: require('../../webpack.config.js'),
watchOptions: {},
}
on('file:preprocessor', webpack(options))
injectDevServer(on, config)
return config
}
cypress.json
{
"component": {
"componentFolder": "src/tests/components"
},
"integrationFolder": "src/tests/integration"
}
webpackconfig.js
var path = require('path')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.js$|jsx/,
exclude: [/node_modules/],
use: [
{
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
},
},
],
},
],
},
resolve: {
alias: {
'~': path.resolve(__dirname, 'src'),
},
},
}
packjage.json
"devDependencies": {
"#cypress/react": "5.12.4",
"#cypress/webpack-dev-server": "1.8.3",
"#cypress/webpack-preprocessor": "^5.11.1",
"#types/jwt-decode": "^3.1.0",
"babel-loader": "^8.2.3",
"cypress": "9.5.2",
"webpack-dev-server": "3.2.1"
}
I managed to do the following solution:
plugins/index.js
const { startDevServer } = require('#cypress/webpack-dev-server')
const webpackConfig = require('../../webpack.config.js')
module.exports = (on, config) => {
on('dev-server:start', async (options) =>
startDevServer({ options, webpackConfig }),
)
return config
}
cypress.json
{
"component": {
"componentFolder": "src/tests/unity"
},
"integrationFolder": "src/tests/integration"
}
webpack.config.js
var path = require('path')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.js$|jsx/,
exclude: [/node_modules/],
use: [
{
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
},
},
],
},
],
},
resolve: {
alias: {
'~': path.resolve(__dirname, 'src'),
},
},
}

Can't use Material UI in external library with webpack/rollup/react

I'm working on a component library that wraps some of the MaterialUI components and implements others to be used in a larger project. While setting up the library I had to setup webpack in order to be able to import and bundle images and css files in my library.
This library is located nested in the folder of the main project, where I add it as a dependency with npm i ./shared/path_to_library. this seems to work fine, since the typescript is working correctly and the npm start gives me no error. Then when I open it in a browser I get the following error page:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
But this error only occurs if I try to use any component from #mui/material inside my library. Exporting handmade components and using them in the main project works fine, but using any material component wrapped by my own component and then using it in the project brings me to this error. I also tried to move from webpack to rollup but I ended up getting the same problem.
Here are my config files for webpack and rollup:
rollup.config.js
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "#rollup/plugin-typescript";
import dts from "rollup-plugin-dts";
const pkg = require("./package.json");
const config = [
{
input: "src/index.ts",
output: [
{ file: pkg.main, format: "cjs", sourcemap: true },
{ file: pkg.module, format: "esm", sourcemap: true },
],
plugins: [
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
],
},
{
input: "lib/esm/types/index.d.ts",
output: [{ file: "lib/index.d.ts", format: "esm" }],
plugins: [dts()],
},
];
export default config;
webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/index.ts",
mode: "development",
output: {
path: path.resolve(__dirname, "lib"),
filename: "[name].js",
libraryTarget: "umd",
library: "my-core-library",
umdNamedDefine: true,
},
devtool: "source-map",
module: {
rules: [
{
test: /\.css?$/,
use: ["style-loader", "css-loader"],
exclude: /node_modules/,
},
{
test: /\.tsx?$/,
use: ["babel-loader", "ts-loader"],
exclude: /node_modules/,
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: ["file-loader"],
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
},
externals: [
{
react: "react",
"react-dom": "react-dom",
"#mui/material": "#mui/material",
"#emotion/react": "#emotion/react",
"#emotion/styled": "#emotion/styled",
"#mui/lab": "#mui/lab",
},
],
};
I'm running out of ideas :(
This is probably happening because multiple instances of React are loaded. You can check with npm ls react, all react packages should be deduped
A short term solution is to link the react from the library, ie
npm link ../shared/path_to_library/node_modules/react
However you would have to re-link that everytime you install an npm package.
I think you need to configure your .babelrc as following:
"presets": ["#babel/preset-env", "#babel/preset-react", "#babel/preset-typescript", "jest"],
"plugins": [
[
"babel-plugin-transform-imports",
{
"#material-ui/core": {
"transform": "#material-ui/core/${member}",
"preventFullImport": true
},
"#material-ui/icons": {
"transform": "#material-ui/icons/${member}",
"preventFullImport": true
}
}
]
]

Jest : TypeError: require(...) is not a function

The application is written by React with ES6 so import and export statements are used inside the application. So Jest is configured to work compatible with ES6, but compiled node_modules dependencies are causing an error which is
TypeError: require(...) is not a function
when tests started.
I assume this is happening because Jest configured to work with babel-jest to handle import statements, but compiled codes are using require for handling the modules. I tried to exclude node_modules folder, but nothing changed. I think, ES6 modules using compiled modules placed into the node_modules as a dependency because of that it cannot be excluded? Is it possible?
Also, I am having a problem to understand how does jest handle both import and require at the same time? If ES6 codes are compiled first then each module will be handled as require after that compiling process. So what is the problem?
Here are the configurations
jest.config.js
module.exports = {
clearMocks: true,
moduleNameMapper: {
"^.+\\.(js|jsx)$": "babel-jest",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/mocks/fileMock.js",
"\\.(css|scss|sass|less)$":
"<rootDir>/mocks/styleMock.js"
},
modulePathIgnorePatterns: [
"node_modules/"
]
};
babel.config.js
/* eslint-disable */
module.exports = {
presets: [
"#babel/preset-react",
[
"#babel/preset-env",
{
targets: {
browsers: ["ie >= 9", "safari >= 8"]
}
}
]
],
plugins: [
["#babel/plugin-proposal-decorators", { legacy: true }],
[
"#babel/plugin-proposal-class-properties",
{ loose: true }
],
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-transform-object-assign",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-transform-runtime"
],
env:{
test:{
plugins: [
["#babel/plugin-proposal-decorators", { legacy: true }],
[
"#babel/plugin-proposal-class-properties",
{ loose: true }
],
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-transform-object-assign",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-transform-runtime"
]
}
}
};
If you are tying to import any file for example a font file, then simply create a mockFile that just have
// mockFile.ts or mockFile.js
export default {};
and then in jest.config.js
moduleNameMapper: {
'^.+\\.(woff2)$': '<rootDir>/<path to file>/mockFile.ts',
},
This will resolve to the mockFil when it will try to import a font file. You can also add other file extentions like '^.+\\.(jpg|png|woff2)$: '<rootDir>/<path to file>/mockFile.ts'.
It should work.

Webpack require unmanaged script

I have a problem with dynamic require js files after webpack bundling.
Environment:
webpack, ts-loader, typescript.
src/index.ts:
require(path.resolve(__dirname, './test.js'));
dist/test.js:
console.log('I should be printed after require # index');
I don't know why but webpack think that there is no file:
1) Warning while running webpack -p
WARNING in ./src/index.ts
5:0-43 Critical dependency: the request of a dependency is an expression
# ./src/index.ts
2) Error while running script:
Error: Cannot find module "C:\Users\user\path\to\dist\test.js".
3) My webpack config is:
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
index: "./src/index.ts"
},
output: {
filename: "[name].js"
},
target: "node",
externals: [ nodeExternals() ],
node: {
"__dirname": false
},
resolve: {
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{ test: /\.tsx?$/, loader: "ts-loader" }
]
}
}
Expected:
NodeJS just dynamically require path while index.js script execution.
Please help to setup that properly.
Thanks!
Problem solved using __non_webpack_require__ function.

Making export default work with Babel, webpack and Node.js

I can't figure out why my code doesn't work.
I am building a ES6 style class and want to export it to be able to use it somewhere else in the server side. I put the code into a file called PlayerManager.jsin the server folder.
I put my client code in the src folder. And my server code in my server folder and server.js outside of server folder.
Here is the directory structure:
Root
- dist
- node_modules
- public
- server
- src
server.js
webpack.base.js
webpack.dist.js
package.json
.babelrc
PlayerManager.js file:
class PlayerManager {
constructor() {
if (! PlayerManager.instance) {
this.playerList = {};
this.bulletList = {};
this.initPack = {player: [], bullet: []};
this.removePack = {player: [], bullet: []};
PlayerManager.instance = this;
}
return PlayerManager.instance;
}
resetData() {
this.initPack.player = [];
this.initPack.bullet = [];
this.removePack.player = [];
this.removePack.bullet = [];
}
}
const instance = new PlayerManager();
Object.freeze(instance);
export default instance;
However, when I use npm run dev which runs node server.js it throws an error saying
export default instance;
^^^^^^
SyntaxError: Unexpected token export
at Object.exports.runInThisContext (vm.js:53:16)
Here is the configuration for babel in webpack:
const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: {
main: './src/main'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].bundle.js'
},
plugins: [
new CopyWebpackPlugin([
{ from: 'public/img',
to: 'static' },
{ from: 'public' }
])
],
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
//include: path.join(__dirname, 'src')
exclude: [
path.resolve(__dirname, "node_modules"),
],
},
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=90000' }
]
},
resolve: {
extensions: ['', '.js']
}
};
In .babelrc:
{
"presets": [
"es2015"
],
"sourceRoot": "./src"
}
In my package.json file:
"scripts": {
"build": "npm run lint && npm run release",
"lint": "./node_modules/.bin/eslint ./src/**/*.js",
"dev": "node server.js",
"release": "NODE_ENV=production webpack --config ./webpack.dist.js --progress",
"test": "./test/*.test.js --compilers js:babel-core/register --recursive --reporter spec"
},
Webpack is a bundler for producing packages that run on the client (in the browser), it is not aware of or concerned with code on the server. (Unless you are doing universal application stuff.)
You will notice too that your npm dev script is simply asking node to load the server.js file, which is (correctly) not mentioned anywhere in your Webpack config.
You are looking for babel-register:
One of the ways you can use Babel is through the require hook. The require hook will bind itself to node’s require and automatically compile files on the fly.
Create an "entry" file that first requires babel-register and then requires your server.js file:
// server-entry.js
require('babel-register')
require('./server.js')
Now change your npm dev script to be node server-entry.js.
______
Aside: it is necessary to create an entry file as babel-register cannot transpile the file in which it is invoked. For example, this would fail:
// server.js
require('babel-register')
export default function () {}

Categories

Resources