Couldn't find preset "env" relative to directory using babel CLI - reactjs

I'm struggling to get my jsx files compiled using babel + presets. My project structure is a bit non-standard as js/jsx files are placed in a sibling directory of the config/build files:
.
├── frontend_config
│ ├── node_modules
│ │ ├── babel-cli
│ │ ├── babel-core
| | | ...
│ ├── package-lock.json
│ └── package.json
├── jsx
│ ├── foo
│ │ ├── Bar.jsx
...
I've narrowed down the issue to the minimal by trying to run babel from the terminal, inside the frontend_config directory I run:
npx babel ../jsx/foo/Bar.jsx --presets=env,react
Couldn't find preset "env" relative to directory "../jsx/foo"
I've installed both babel-preset-env and babel-preset-react but I don't know how to tell babel where are they placed. I've also tried using a .babelrcfile but the behavior is the same.
My setup is:
$ npx babel --version
6.26.0 (babel-core 6.26.0)
$ node --version
v8.9.4

You have installed babel dependencies like cli, presets, plugins in frontend_config folder and you're transpiling JSX files which are not placed in same root babel installed. That is why, it shows like
Couldn't find preset "env" relative to directory
do like below in your webpack/grunt/.babelrc :
use absolute paths
or use require like below :
var babelenv = require('babel-preset-env');
var babelreact = require('babel-preset-react');
var babelamd = require('babel-plugin-transform-es2015-modules-amd');
and
presets: [ babelenv, babelreact],plugins : [ babelamd ]
Hope it helps.

run npm install #babel/preset-env --save-dev
More info # https://babeljs.io/

For anyone having this issue, the solution when using Babel 6 and placing node_modules in a different directory than the project root is to use absolute paths. Hence the babel call would look like:
npx babel ../jsx/foo/Bar.jsx --presets /Users/foo/bar/frontend_config/node_modules/babel-preset-env/,/Users/foo/bar/frontend_config/node_modules/babel-preset-react/
Credit to the answer goes to loganfsmyth

You can also just put this in your .babelrc file if you like
{
"presets" : [ "/Users/foo/bar/frontend_config/node_modules/babel-preset-env" ]
}

Related

Jest doesn't follow files in a symlink folder and tries to use the main shared folder

The question is - how to force Jest to follow symlinked shared folder file structure but not main shared folder?
I have the next files structure:
root
├── projects
│ ├── A
│ │ ├── node_modules
│ │ ├── shared (symlink ../../shared-main)
│ │ ├── components
│ │ ├── settings.ts
│ ├── B
│ │ ├── node_modules
│ │ ├── shared (symlink ../../shared-main)
│ │ ├── components
│ │ ├── settings.ts
├── shared-main
│ ├── utils.ts
│ ├── config.ts
In my projects, A and B, I use utils from the shared folder. Utils.ts uses config.ts where imports settings files by path './settings.ts', but inside the shared-main folder, it looks like "file doesn't exist" (it is ok). But Jest in a project's tests when it meets using a shared file test fails with the error: "../../shared-main/config.ts:9:35 - error TS2307: Cannot find module '../settings' or its corresponding type declarations."
How to get around this and force Jest to use config.ts from the symlink folder instead of the main one?
How about "testRegex": ["test/.*.[jt]s"], in your jest config so it doesn't try and find shared files, if you're using shared files across multiple projects then no single project should test those files, they should only test their own files.
However I'm not so sure that symlinks are your problem, when using typescript like this and trying to use files outside of your project rootDir it will not find the types for it or it will complain that it can't find the types for it if you've added it to tsconfig include/exclude. Right now I can only assume that you're using tsc --project with specific config files for each project.
// tsconfig.json
"include": ["projectA/**/*.ts"],
If you've done something like that then it won't find any types outside of projectA so anything in config.ts and utils.ts will not have any types or be able to find any modules, unless they're included in your tsconfig.
To show a simpler example if I have:
// tsconfig.json
...
includes: ["src/**/*.ts"]
...
Along with a directory structure like this:
- tsconfig.json
- example.ts
- src
Then anything in example.ts will not be able to find its types or module imports.
The way I get around this issue in my project is to use ts-jest along with specifying where to find tests, along with overriding the globals rootDir.
// .jestrc.json
"testRegex": ["test/.*.[jt]s"],
...
"globals": {
"ts-jest": {
"tsconfig": {
"rootDir": "."
}
}
}

Install and use Storybook in a demo page

I am creating a personal project in TypeScript. It should be a library that exports React components and TypeScript functions. The idea is therefore to publish this library on npm in the future.
There is also a demo page within the project and this is where I would like to use Storybook to test React components.
This is the structure of the project:
.
├── demo/ # demo page
│ └── Home.tsx # where I would like to use Storybook
│ └── index.html
│ └── index.tss
│ └── style.css
├── dist/ # distributable version of app built using Parcel
├── node_modules/ # npm managed libraries
├── src/ # project source code
│ └── lib/ # folder for your library
│ └── myFuncion.ts # function to export
│ └── MyComponent.tsx # react component to export
│ └── index.ts # app entry point (it simply contains the exports of myFunction and myComponent)
├── .eslintrc.js
├── .gitignore
├── package.json
├── tsconfig.json
├── ...
I have read the Storybook documentation and it recommends to install Storybook by running npx sb init. I tried but the problem is that the stories are put in the project src directory, not in the demo page:
.
├── demo/ # demo page
│ └── Home.tsx # where I would like to use Storybook
│ └── index.html
│ └── index.tss
│ └── style.css
├── dist/ # distributable version of app built using Parcel
├── node_modules/ # npm managed libraries
├── src/ # project source code
│ └── lib/ # folder for your library
│ └── myFuncion.ts # function to export
│ └── MyComponent.tsx # react component to export
│ └── stories/ # Storybook <<---
│ └── index.ts # app entry point (it simply contains the exports of myFunction and myComponent)
├── .eslintrc.js
├── .gitignore
├── package.json
├── tsconfig.json
├── ...
And the storybook script that is created is this:
"scripts": {
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
but I would like something like:
"scripts": {
"storybook:demo": "start-storybook -p 6006",
"build-storybook:demo": "build-storybook"
},
So how can I install and use Storybook only on the demo page?
Looks like you're ultimately trying to have multiple source directories. This is supported by both TypeScript and Storybook, it just needs a bit of configuration.
tsconfig.json should have the include option set to:
"include": [ "src", "demo" ]
This tells TypeScript (or its Babel loader) to compile files in src and demo.
.storybook/main.js should have the stories option set to:
stories: [
'../demo/**/*.stories.mdx',
'../demo/**/*.stories.#(js|jsx|ts|tsx)',
],
This specifies which files should be interpreted as stories and in our case it would load *.stories.mdx/js/jsx/ts/tsx recursively from the demo folder.
Also note that the stories folder is just an example folder created by Storybook and you can safely delete it. Stories can be in any of the directories processed by TypeScript as long as it matches the patterns specified in .storybook/main.js.
You can even have multiple Storybooks with multiple configs in a single project, but that may not be what you're after. Just in case, though, the command would be start-storybook -p 6006 -c path/to/config/.storybook
If I understood correctly, you want to build a components library and have demo app for your components.
I don't think there is a way to use Storybook in an existing app. This would mean you would have to build your demo app and use some components from Storybook to show case components in your app. To my knowledge this is not possible. It might be, but it seems complicated and I don't know of any docs on this.
I think the Storybook app is (or should be) your demo app.
Storybook can render mdx files so you can add any content to it and get a demo app.
What you could try:
Move your demo app content and component stories to the demo folder
Migrate Home.tsx to a mdx file
Change Storybook's config to load stories from '/demo`
To a degree, you can change Storybook's styling and "make it your own" and this can become your demo app.
Until I discovered Storybook I used a home-made components show case app with react-live. Might want to take a look at it but I think Storybook is is better and easier to maintain.

Jest: how to create a __tests__ folder which mirrors the src directory?

Using Jest (for React testing) I would like to have my tests in their own directory, mirroring the src dir. Ex:
appRoot
├── src
│ └── components
├── __tests__
│ └── components
I do not want to have my tests inside the src folder
The default config of at least Jest 26.6 uses these globs:
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[tj]s?(x)"
],
__tests__/ can be anywhere in your project directory, including the top level alongside src/. It does not have to be in your src/ directory.

Jest finds tests but doesn't collect coverage

I trying to collect test coverage for this project using
yarn test --coverage # i.e. "react-scripts test --coverage"
My jest config is this:
"jest": {
"collectCoverageFrom": [
"src/**/*.ts*"
],
"coverageThreshold": {
"global": {
"lines": 90,
"statements": 90
}
}
}
and my folder structure is as follows:
.
├── package.json
├── postcss.config.js
├── public/
├── README.md
├── src/
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── assets/
│   ├── components/
│   │   ├── Emoji/
│   │   │   ├── Emoji.test.tsx
│   │   │   ├── Emoji.tsx
│   │   │   └── index.ts
│   │   └── Home/
│   │   ├── Home.css
│   │   ├── Home.test.tsx
│   │   ├── Home.tsx
│   │     └── index.ts
│   ├── index.css
│   ├── index.tsx
│   ├── react-app-env.d.ts
│   └── serviceWorker.ts
├── tsconfig.json
├── yarn-error.log
└── yarn.lock
Jest is being able to find all the tests but it fails to collect coverage:
PASS src/components/Home/Home.test.tsx
PASS src/components/Emoji/Emoji.test.tsx
PASS src/App.test.tsx
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 0 | 0 | 0 | 0 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 3 passed, 3 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 3.432s
Ran all test suites.
What am I missing? What should I add to the configuration to get the coverage?
Any hint is welcome :)
Tries
Changing the glob pattern to "src/**/*.{js,jsx,ts,tsx}".
Removing node_modules and then running yarn to reinstall everything.
Removing node_modules and yarn.lock, and then reinstall everything, which led to another bug, which I tried to solve installing that particular dependency, but it didn't work.
Cloning the repository from GitHub and then running the command on the fresh version.
Switching to a different Node version (v10.16.2, and v11.7.0).
The quick fix I said in my comment, using --watchAll instead, eg: react-scripts test --coverage --watchAll.
Just for future reference, I think ideally we should be using --watch, which would only run on changed files, but it gave me the same trouble. I think it's related to this issue '--coverage --watch' should calculate coverage for all files at first iteration and also this issue No coverage when running in watch mode. I'm not sure why it worked for some people and not you, presumably something to do with Git and staging of files.
Not necessarily the solution in the original questioner's case, but i ran into the exact same problem and this was my solution:
I found that when upgrading jest (from 23 to 26) that i had this issue, and the resolution was to run with the --no-cache option. Presumably they changed something about these coverage reports internally such that the cached data was incompatible.
Seems to be working fine on Linux Mint 19.2. I'd suggest changing your jest config to something a bit more flexible:
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!<rootDir>/node_modules/"
],
"coverageThreshold": {
"global": {
"lines": 90,
"statements": 90
}
}
}
And then change your package.json test script if you're using npm (with yarn you can just append --coverage, for example: yarn test --coverage; however, with npm, it'll just ignore it). So I'd suggest either doing this:
"test": "react-scripts test --coverage",
Or, I'd recommend using yarn over npm. To install yarn, use one of the following methods.
Working:
What helped me is that instead of
npm run test
or
npm run test --watchall
I did this:
npm run test a
and
npm run test a -- --coverage
Been there...
You're missing one more parameter in Jest config:
collectCoverage: true
In our case the problem was with the jest rootDir setting (in our package.json) which we had set to tests. Jest therefore ignored our src/ folder where our actual source code was. The rolution was to tell jest about both folders:
package.json old
"jest": {
"rootDir: "tests"
}
package.json new
"jest": {
"roots": [
"src",
"tests"
]
}
Seems the problem is with the flag --watchAll
Without setting it to false it does not generate coverage
react-scripts test --reporters=jest-junit --reporters=default --coverage --coverageDirectory='testresults/coverage' --coverageReporters=cobertura --coverageReporters=lcov --watchAll=false
For me, I've changed the folder's name and forgot to update the collectCoverageFrom key under the jest.config.ts file.
For me, <rootDir> was missing, it worked fine after adding it.
"collectCoverageFrom": [ "<rootDir>/**/*.{js,jsx,ts,tsx}" ]
In my case, I was testing React Native/Expo app with the option cacheDirectory: '.jest/cache'. Deleting the .jest directory has solved the issue for me.
In my case I was able to get to work by deleting cache and do npm install. In windows cache location (~\AppData\Roaming\npm-cache)
I had a similar problem to yours and these are the solution I found recently.
In package.json I have to set the collectCoverageFrom and coverageReporters to:
{ "jest": {
"collectCoverage": true,
"coverageReporters": [
"cobertura",
"lcov",
"text"
],
"collectCoverageFrom": [
"src/**/*.{ts,tsx,js,jsx}",
"!src/**/*.d.ts"
]
}
And since I'm using npm:
npm test --coverage
Btw, I'm using Vite—just in case you're curious.
1º - Try removing your jest.config file.js (if it exists).
2º - Keep the default Jest settings only in your package.json file, so you don't get confused when compiler both settings.
like this:
"jest": {
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|#react-native(-community)?)|expo(nent)?|
#expo(nent)?/.*|#expo-google-fonts/.*|react-navigation|
#react-navigation/.*|#unimodules/.*|
unimodules|sentry-expo|native-base|react-native-svg)"
],
"collectCoverage": true,
"collectCoverageFrom": [
"**/*.{ts,tsx,js,jsx}",
"!**/*/*.d.ts",
"!**/coverage/**",
"!**/node_modules/**",
"!**/babel.config.js",
"!**/jest.setup.js"
]
}
3º - With these settings made, in package.json file, separate the scripts to run the Jest. One for testing and one for collecting Coverage
like this:
"scripts": {
...,
"test": "jest --watch --coverage=false",
"testWithCoverage": "jest"
}
In Node.js too, adding collectCoverageFrom in package.json helped me to find the uncovered files.
My package.json,
{
...
"jest": {
"testEnvironment": "node",
"coveragePathIgnorePatterns": ["/node_modules/", "api-testing"],
"testPathIgnorePatterns": ["/node_modules/", "api-testing"],
"collectCoverageFrom": ["**/controllers/*.js"]
}
}
Before adding collectCoverageFrom
After adding collectCoverageFrom
Basically, without adding collectCoverageFrom, it only includes the files that has test cases (i.e. the .test.js files in the usual naming convent) .
Add this to your package.json
"jest": {
"testPathIgnorePatterns": [
"<rootDir>/path/to/ignore/"
]
}
This will solve the issue of yours instead of specifying a lot of these commands

Linking and using local UI module in react-native

Disclaimer; I am new to react & react-native. I've downloaded a UI module and am attempting to use it in my project. This is what the folder structure looks like:
├── myProject
│   ├── README.md
│   └── src
│   └── client
│   └── {actual react-native project}
└── react-native-ui-module
├── node_modules
├── package-lock.json
├── package.json
└── src
I've added react-native-ui-module to myProject/src/client/package.json like so:
"react-native-ui-module": "file:../../../react-native-ui-module",
From there, I've executed the following command:
$ npm install
$ react-native link
I can see the module in node_modules after the above steps.
I've expected to then use the module like so:
import { Button } from 'react-native-ui-module';
However, I'm getting an error that states that the Modulereact-native-ui-module` does not exist in the Haste module map. I've tried following the error message's suggestion, which is:
This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
Clear watchman watches: watchman watch-del-all.
Delete the node_modules folder: rm -rf node_modules && npm install.
Reset Metro Bundler cache: rm -rf /tmp/metro-bundler-cache-* or npm start -- --reset-cache.
Remove haste cache: rm -rf /tmp/haste-map-react-native-packager-*.
I've also tried using relative and absolute paths in the import statement. Is there a better way of importing and installing the module? And what other troubleshooting steps can I take to actually use the module?
Also, to clarify; this is a module that I've purchased and manually downloaded, so it's not available from npmjs.
The short thing you can do, considering your current situation, is to copy the ui module into the node_modules of your {actual react-native project}, then the ui module will be available for you to use in the imports, in this way you don't even need to add the module into your package.json, but this way is just for testing what the ui module can do.
The correct way is to find this ui module in the npm site, and use the command npm install --save [name-of-the-ui-module], then ui module will be available for you to use in your imports.
(Updated considering comments bellow)
To avoid Headaches with npm, considering that your library is not in the npm repository, you can also include this library in a lib folder into your project, and use it like you were using any other component.

Resources