Jest config not picked in git submodule npm package from root - reactjs

For an RN app.
I have a project structure like
root git repo
|-jest.config
|-package.json
|-screens/
|--git submodule
|--git submodule
|--.lintstagedrc
one repo at root with package.json and jest.config
and multiple git submodules in screens folder
Each submodule is a npm package which is symlinked in node modules and added in package.json pointing to the git branch.
Now what i wanted to do was add a precommit hook in each submodule and use the root configurations for jest to run when anything is committed in the submodule.
I am using husky and have defined a .lintstagedrc file in the screens folder which would be picked while running husky.
{
"./**/app/**/*.{js,jsx,ts,tsx}": [
"eslint --fix --ext .js,.jsx,.ts,.tsx --plugin tsc --rule 'tsc/config: [2, {configFile: \"../../../tsconfig.json\"}]'",
"jest --config ../../../jest.config.js --bail --forceExit --passWithNoTests --findRelatedTests"
]
}
i am trying to set the jest config using the args however when the commit hook runs it does not pick the config and gives a type error for RN polyfill files
Syntax Error node_modules/#react-native/polyfills/error-guard.js: Missing semicolon. (14:4)
> 14 | type ErrorHandler = (error: mixed, isFatal: boolean) => void;
The same runs correctly if the files are not part of submodule and directly in the root repo(while being at the same path)
when running npx jest --showConfig it is correctly showing the required jest config. but running jest always fails.
How do i get jest to pick the current config and assume the root folder for config is the root repo and not the submodule npm package as i suggest having a package.json defined in submodule might be causing issues
Or that given the submodule is symlinked to node_modules folder at root might be the issue.
Jest config(payments is an example submodule)
module.exports = {
// The preset is a node environment that mimics the environment of a React Native app. Because it doesn't load any DOM or browser APIs, it greatly improves Jest's startup time.
verbose: true,
preset: 'react-native',
// It helps you greatly improve the test speed.It does so by creating a cache of compiled modules so that it doesn't have to compile the node_modules every time we run tests.
cacheDirectory: './cache',
// Defines the files which we want to skip while generating coverage reports.
// coveragePathIgnorePatterns: ['./src'],
// Defines the threshold limit for all the tests to pass.If the coverage is less than the defined limit, the tests would fail.This helped us in keeping code coverage high throughout development.
coverageThreshold: {
global: {
// global thresholds
branches: 23,
functions: 25,
lines: 32,
statements: 32,
},
},
globals: {
'ts-jest': {
diagnostics: false,
},
},
collectCoverageFrom: [
'./src/**/*.js',
'./src/**/*.ts',
'./src/**/*.tsx',
'!**/node_modules/**',
'!**/vendor/**',
],
testPathIgnorePatterns: ['src/.+((?:.ignored)|(?:mock)).(ts|js)x?'],
transform: {
'^.+\\.(ts|tsx|js|jsx)$': 'babel-jest',
},
// All the npm modules which need to be transpiled are added here.These modules are basically ES6/ 7 modules.
transformIgnorePatterns: [
'/node_modules/(?!(jest-)?#?react-native|payments|react-clone-referenced-element|react-navigation|#react-native-community|rn-range-slider|victory|react-native-svg|recoil)',
],
setupFilesAfterEnv: [
'<rootDir>/src/tests/setupTests.js',
'<rootDir>/node_modules/react-native-gesture-handler/jestSetup.js',
'#testing-library/jest-native/extend-expect',
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleNameMapper: {
'\\.svg': '<rootDir>/src/tests/mocks/svgMock.js',
'^src/(.*)': '<rootDir>/src/$1',
'^config/(.*)': '<rootDir>/config/$1',
'^app/(.*)': '<rootDir>/app/$1',
'^setup/(.*)': '<rootDir>/setup/$1',
'^payments/(.*)': '<rootDir>/src/screens/payments/$1',
},
notify: true,
notifyMode: 'always',
};

Related

Storybook webpack config not working - trying to run Storybook out of separate local project than components

I have a mature CRA-based React app running with Webpack 5. I would like to have a separate project (in git, etc) where Storybook lives and points to the components in the app. (The app has tons of devs in and out of it, and dropping a bunch of Storybook packages in there, as well as introducing legacy-peer-dependencies thanks to webpack 5, would be quite frowned upon).
I also want devs to have a good experience being able to use Storybook to write components, so I want Storybook to see the current code of the project components, not some exported package. And same as above, there are many devs and a lot of inertia, so moving components to a separate standalone library is not an option.
My ideal for local development:
components and stories: /MyProject-App/src/Components/...
storybook app. : /MyProject-Storybook/stories/...
(Production I'm not worried about yet)
Installing Storybook inside the app works fine (as long as you run with --legacy-peer-deps). I am using the npx storybook init script and it works fine. But if I try to run Storybook out of a separate directory and target the app directory's Components, it breaks. If I run Storybook out of the app, and point it to stories/components outside that repo (which I copied and pasted just as a debugging measure), it breaks. Going up and out of the current project root breaks.
To do this, I am trying to point stories in /MyProject-Storybook/.storybook/main.js to ../../MyProject-App/src/Components.... When I do this and npm run storybook, I get the error output:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
**You may need an additional loader to handle the result of these loaders.**
The error is always on some basic ES6 syntax, arrow functions etc. If I run the same Storybook install out of MyProject-App (same version numbers / same main.js just pointed at the local path instead of the ../other path) it works.
In addition to this, I tried it the other way - running storybook out of the App folder (where I know it runs), and only changing the main.js stories directory to an outside-that-repo folder where I copied my Components and stories into. It breaks in the same way - I get the same You may need an additional loader to handle the result of these loaders. message, with it pointing to any example of ES6 syntax as an 'error'.
I found this similar question - Storybook can't process TS files outside of the project
recommending to look into Storybook's webpack loaders - https://storybook.js.org/docs/react/builders/webpack
So I updated my .storybook/main.js to be the following:
module.exports = {
stories: [
'../../MyProject-Storybook/src/**/*.stories.mdx',
'../../MyProject-Storybook/src/**/*.stories.#(js|jsx|ts|tsx)'
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/addon-interactions',
'#storybook/preset-create-react-app'
],
framework: '#storybook/react',
core: {
builder: '#storybook/builder-webpack5'
},
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
reportFiles: ['../**/src/**/*.{js,jsx}', '../../MyProject-Storybook/**.stories.{js,jsx}']
}
}
]
});
config.resolve.extensions.push('.js', 'jsx');
return config;
}
};
but to no avail - output from npm run storybook remains unchanged, an excerpt:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
You may need an additional loader to handle the result of these loaders.
| backgroundColor: { control: 'color' },
| },
> } as ComponentMeta<typeof Button>;
|

Environment variables in manifest.json - Chrome Extension

Is it possible to set environment variables in the manifest.json file of a Chrome Extension?
Like wOxxOm said, I used webpack to proccess manifest.json.
In my case, I needed to set version automatically on manifest file.
I added to webpack script:
plugins: [
new CopyWebpackPlugin([
{
from: "public/manifest.json",
to: "manifest.json",
transform(content, path) {
return modify(content)
}
}
]),
]
And the modify function replaces version on file for the parameter:
function modify(buffer) {
var manifest = JSON.parse(buffer.toString());
let argv = process.argv[2];
if (argv) manifest.version = argv.split("=")[1];
let manifest_JSON = JSON.stringify(manifest, null, 2);
return manifest_JSON;
}
So, I build like "yarn build --version=x.x" and webpack do what I need.
PS: if you're going to use this, remember to change:
the manifest.json directory, if necessary;
the value in the modify function, in my case it was version
As the OP has mentioned in her answer, using the copy-webpack-plugin in the webpack.config.js file is the way to go if you're building your Chrome Extension with React. However, if your React app is based on create-react-app, directly editing the webpack.config.js file (which is located in node_modules/react-scripts/config) is not recommended.
In such a case, use craco, which is an npm package that can be used to customize an app based on create-react-app. Here's how you do it:
Install craco into your project using npm i #craco/craco.
Install copy-webpack-plugin as a dev-dependency in your project using npm i --save-dev copy-webpack-plugin.
Let's suppose we're creating a development and a production build of our Chrome Extension. Let's also suppose we've already assigned "version": "0.1.0" in our Chrome Extension's manifest.json. Depending on the build type, we'd like to assign accordingly the version_name field in our Chrome Extension's manifest.json, e.g., "version_name": "0.1.0 dev" for development and "version_name": "0.1.0" for production. In your React app's package.json, introduce two fields (the script names can be whatever you wish) as follows:
"scripts": {
...
"build-dev": "CRX_ENV=dev craco build", // or "set CRX_ENV=dev&& craco build" in the case of Windows
"build-prod": "CRX_ENV=prod craco build", // or "set CRX_ENV=prod&& craco build" in the case of Windows
...
}
Create a new file called craco.config.js in the root of your project. As per your need, do something similar to the following in the craco.config.js file:
const CopyPlugin = require("copy-webpack-plugin")
module.exports = {
webpack: {
plugins: [
new CopyPlugin({
patterns: [
{
from: "public/manifest.json",
to: "manifest.json",
transform(content, path) {
return modifyManifest(content)
},
},
],
}),
],
},
}
function modifyManifest(buffer) {
const manifest = JSON.parse(buffer.toString())
if (process.env.CRX_ENV === "dev") {
manifest.version_name = `${manifest.version} dev`
} else if (process.env.CRX_ENV === "prod") {
manifest.version_name = `${manifest.version}`
}
const manifestJson = JSON.stringify(manifest, null, 2)
return manifestJson
}
Run npm run build-dev. It will create a folder called build in your project root. This build folder is your unpacked Chrome Extension, which you can load into Chrome using the "Load unpacked" button on the chrome://extensions page. Once loaded, you should be able to see 0.1.0 dev as the version name of your Chrome Extension.
Delete the build folder created from the previous step and run npm run build-prod, and repeat the same steps. You should be able to see 0.1.0 as the version name of your Chrome Extension on the chrome://extensions page.

I want to add a babel plugin inside create-react-app

I want to add the following babel configuration in react-scripts I don't want to eject from cra I want to keep using it without ejecting. I see there is a way to fork the repo and add your custom configuration. But I want to know where exactly I can paste this.
// .babelrc or babel-loader option
{
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] // `style: true` for less
]
}
There is, in theory, customize-cra, which lets you do things like override Babel plugins.
Here is a list of things you can do.
It doesn't appear to be maintained at time of writing, and for me didn't seem usable if your project is modules-based (ie import) as opposed to require.
CRA itself recommends forking their scripts as an alternative to ejecting, which is a pretty bold statement.
If you wish to override a property of one of the config files of React, you can just create that config file in your project's main directory and just set that single property, this will override that property in React's configuration. For babel you can just add it as a property in package.json like so:
"babel": {
"presets": [ ... ],
"plugins": [ ... ],
}
If you run npm run-script eject you are going to get a copy of all the config that ReactJS uses for your project in the main directory of your project/config, from there you can edit whatever you like, keep version tracking of your changes and not mess with the react repository.
If you insist on forking it you can fork the main create-react-app repository from here, which contains the react-scripts here

How to transpile node_modules folder using just babel 7?

Trying to unit test reactjs application using mocha but getting error from es6 features (import/export) used inside node_modules folder. The application in question is transpiled using babel but since one of react component is using a module from node_modules its throwing error Syntax Error:Unexpected token export. I am aware that babel ignores node_modules folder by default, but not sure how to approach this. Any help would be appreciated. Thanks.
Test Command :-
"test": "SET NODE_ENV=test&& mocha --require #babel/register --require ignore-styles -r jsdom-global/register \"./src/**/*.test.js\"",
babel.config.js :-
module.exports = function (api) {
const presets = ["react-app"];
const plugins = [
"#babel/plugin-transform-modules-commonjs",
"inline-react-svg"
];
const ignore = [/node_modules/]
api.cache(false);
return {
presets,
plugins,
ignore
}
};
Got it working!. Had to switch from Mocha to Jest since I was using react-app-rewired which was internally configured to use Jest. A small change in config-override.js was needed. Added a jest config with "transformIgnorePatterns": ["node_modules/(?!MODULES_TO_BE_TRANSPILED)"]. Hope it helps others.
try this command, you need to pass ignored directories in command line with --ignored option.
./node_modules/.bin/babel . -d ~/app_compressed/ --ignore node_modules,test,assets,stuff,views,public,test,spec,logs,lib/jasmine_examples,db,routes/api/drafts,**/drafts
Also, make sure to use a babel.config.js file instead of a .babelrc file.
so the config file will look like following.
module.exports = function (api) {
api.cache(true);
return {
babelrcRoots: [
'.',
'./modules/*'
],
ignore: [/node_modules/],
presets: ["#babel/preset-env"]
};
}

Getting an error "Module not found: Can't resolve './User.scss' " when running heroku-postbuild

I am writing a chat using React/Redux/Firebase
I have next structure:
components
User
index.js
User.scss
UserHeader.js
UserItem.js
UserList.js
UserSerach.js
Message
index.js
Message.scss
MessageList.js
...
All styles of components of "type" User are located in the file User.scss
I'm not sure what's right. I don't like a lot of folders with components
My actions:
git add .
git commit --amend --no-edit
heroku create
heroku git:remote -a project-name
git push heroku master
In the file package.json i also write:
"engines": {
"npm": "6.4.1",
"node": "10.14.2"
}
And to start production after installing packages:
"heroku-postbuild": "npm run serve"
During heroku package installation I get an error:
ERROR in ./src/components/User/UserHeader.js
remote: Module not found: Error: Can't resolve './User.scss' in '/tmp/build_0467563cc44feeb52e4f8bb96c6f75fa/src/components/User'
remote: # ./src/components/User/UserHeader.js 3:0-33 8:15-21 10:15-21 14:15-21 16:15-21 19:15-21
remote: # ./src/components/User/index.js
remote: # ./src/components/Chat/Chat.js
remote: # ./src/components/Chat/index.js
remote: # ./src/components/App/App.js
remote: # ./src/components/App/index.js
remote: # ./src/index.js
But I imported the User.scss:
import styles from './User.scss';
The same error pops out for other User components. But I have same structure with one scss file in Message components and there are no errors..
Styles in the webpack config:
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9'
],
flexbox: 'no-2009'
})
]
}
},
'sass-loader'
]
}
I have already tried several other style settings - the same error.
Edit
I found out that the error was in the scss file name (user.scss => User.scss). But I'm getting the same error.
I had a mistake that I fixed after reading that the webpack or the Windows console or the Heroku (I don't remember) caches files. And when you change their location or the names for the Heroku they don't change. Something was like that but I don't remember.
I need to enter something in the console so that changes to files and paths are taken into account. Maybe someone knows?
Edit 2
Solved my stupid problem:
Made a commit on the GitHub by changing the name of the files to the correct ones. It's not working if I change files locally, because of the problem that I wrote above)
Made a git pull
Now the Heroku works :)
But I still want to know how to solve the problem written above.

Resources