I have this component:
import React from 'react';
import VideoTag from './VideoTag';
import JWPlayer from './JWPlayer';
class VideoWrapper extends React.Component {
//... component code
}
That based on some logic renders another component inside ( VideoTag or JWPlayer) but when I try to test it in a jest file i get the error:
Cannot find module './VideoTag'
The three coponents are in the same directory that's why it actually works when I transpile it and see it in action in a browser but looks like Jest is having problems resolving those relative paths, this is the jest file:
jest.dontMock('../src/shared/components/Video/VideoWrapper.jsx');
import React from 'react';
import ReactDOM from 'react-dom';
TestUtils from 'react-addons-test-utils';
import VideoWrapper from '../src/shared/components/Video/VideoWrapper.jsx';
describe('VideoWrapper tests', () => {
it('Render JWPlayer', () => {
let vWrapper = TestUtils.renderIntoDocument(
< VideoWrapper model={model} />
);
});
});
The error is at line:
import VideoWrapper from '../src/shared/components/Video/VideoWrapper.jsx';
How do I tell jest how to handle relative paths?
I also had to add the moduleNameMapper to my jest configuration for my tsconfig path maps in order to get my tests to recognize the path maps I had setup. Something like this:
"moduleNameMapper": {
"^yourPath/(.*)": "<rootDir>\\yourPath\\$1"
}
Hopefully this will help someone down the line!
The problem were not the paths, It was looking for modules only with .js extension, it worked after adding the .jsx in the jest configuration:
"moduleFileExtensions": [
"js",
"jsx"
]
You don't need to add moduleFileExtensions in the configuration for these two options since jest uses ['js', 'jsx', 'json', 'node'] as default file extensions. (Unless you want to specifically skip any option that is)
In my case the issue was the import is also case sensitive. Check your import statement and ensure that it matches the filename exactly!
For others ending up here trying to use Jest with TypeScript: you need to include ts in the moduleFileExtensions, e.g.:
"moduleFileExtensions": [
"js",
"jsx",
"json",
"node",
"ts"
]
You also need a transform for *.ts files:
transform: {
"^.+\\.vue$": "vue-jest",
"^.+\\.js$": "babel-jest",
"^.+\\.(ts|tsx)$": "ts-jest"
},
Related
I want to set up import path aliasing in a typescript/node/express project WITHOUT using other packages like tsconfig-paths and link-module-alias. I would like to do this with built-in nodejs functionality (the Typscript aliasing is already done).
Basically:
// Change
import { myFn } from '../../../utils';
// To
import { myFn } from '#this/utils';
The glimmer of hope I have is with node's subpath imports. Theoretically, I can just add this to my package.json:
"imports": {
"#this/*": "./dist/*"
}
Here's the problem
This works for explicitly importing the *.js files, but it does fails for implied index.js (i.e. Folders as modules)
// Works
import { myFn } from '#this/utils/index.js';
// Does not work
import { myFn } from '#this/utils';
However, I would expect node to resolve the import like this:
if utils is a directory, the import should resolve to */utils/index.js
if utils is a file, the import should resolve to */utils.js
My first thought would be to update the package.json imports to include all possibilities, but this is not supported:
"imports": {
"#this/*": [
"./dist/*",
"./dist/*.js",
"./dist/*/index.js"
]
}
The other option seems to be to define an exports entry for every directory, but that is not scalable.
With --experimental-specifier-resolution=node flag the code below works for me.
index.js:
import { myFn } from '#this';
package.json:
...
"imports": {
"#this": "./utils"
}
...
What worked for me on a typescript node project using esbuild was to define the path twice, but for the second time don't include /*. That will allow you to import the index.ts using #utils while still allowing you to import other files underneath the directory
{
"paths": {
"#src/*": ["src/*"],
"#src": ["src"],
"#utils/*": ["src/utils/*"],
"#utils": ["src/utils"]
}
}
So, I am trying to import a few components from Element-ui on demand, but for some reason it keeps importing the entire library (docs about importing on demand here). See image below.
I already followed this post on how to import individual elements from ElementUI.
I installed the element-ui library with npm.
Then in my main.js file I import components on demand as follows:
import 'element-ui/lib/theme-chalk/button.css';
import 'element-ui/lib/theme-chalk/popover.css';
import { Button } from 'element-ui';
import { Popover } from 'element-ui';
Vue.use(Button)
Vue.use(Popover)
I installed the babel-plugin-component dependency. It uses the following config in .babelrc
{
"presets": [
[
"es2015",
{
"modules": false
}
]
],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
I also use the Message function quite a lot. I used to import this in every component I use the function like they have stated in their documentation:
import { Message } from 'element-ui';
But I've read somewhere that that also imports the entire lib. So I changed that to this:
import Message from 'element-ui/packages/message';
But whatever I do, my bundle (and specifically ElementUI) keeps getting bigger...
What am I missing here?
When I try to run npm jest, the test suite fails to run and gives this error message:
Cannot find module 'app/utils' from 'MoreModal.js'
1 | import React from 'react';
2 | import { Link } from 'react-router';
> 3 | import { fn, api } from 'app/utils';
My jest config is
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/js/__tests__/setup/setupEnzyme.js",
"testPathIgnorePatterns": ["<rootDir>/js/__tests__/setup/"],
},
I've tried fiddling with moduleDirectories, but that does nothing.
My enzyme setup is
Enzyme.configure({ adapter: new Adapter() });
The test:
describe('<MoreModal />', () => {
describe('render()', () => {
test('renders the component', () => {
const wrapper = shallow(<MoreModal />);
const component = wrapper.dive();
expect(toJson(component)).toMatchSnapShot();
})
})
})
How do I get jest to correctly find the modules in the component?
Your bundler probably has something set up for resolution to make app/utils work like that.
If you're using Webpack, https://www.npmjs.com/package/jest-webpack-resolver will help you wire up Jest to use the same resolution rules.
You can try the following:
"jest":{
"modulePaths": [
"<rootDir>/app"
],
"moduleDirectories": [
"app"
]
}
According to Jest documentation:
An alternative API to setting the NODE_PATH env variable, modulePaths
is an array of absolute paths to additional locations to search when
resolving modules. Use the string token to include the path
to your project's root directory. Example: ["/app/"].
It is also possible that your bundler resolves your modules relative to a different directory as very well mentioned by #AKX. Is "app/utils" in the root folder of your project or inside a different one? If that's the case your jest configuration should match your bundler's.
I'm looking at using this Yeoman generator as a starter for a mini project containing a few reusable form components I can publish. The generator builds a module and an example component, directive, pipe and service configured for use (you can see the template files for the generator here).
I then used npm link to allow me to install the generated project in my Angular app, which appears to work fine, as demonstrated below taken from the project's node_modules directory;
I have then imported the module into my module within my Angular app;
import { SampleModule } from 'my-test-library';
#NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
NgbModule,
MomentModule,
SampleModule // <-- Imported Here
],
declarations: [],
providers: []
})
export class TasksModule { }
This module import causes the error Uncaught Error: Unexpected value 'SampleModule' imported by the module 'TasksModule' and I cannot figure out why.
There are two things I notice when comparing the library I have imported with another third party library (e.g. ng-bootstrap)
As I have used npm link to import the library to allow me to test during development the entire folder structure has been imported (rather than just the dist directory. I assume this means the non-dist code is being imported by the TasksModule. If I attempt to import my-test-library/dist I get a module cannot be found error.
Unlike ng-bootstrap my library appears to be missing *.metadata.json files in the output.
My library's tsconfig.json file is as follows (unchanged from generator install)
{
"compilerOptions": {
"noImplicitAny": true,
"module": "commonjs",
"target": "ES5",
"emitDecoratorMetadata": true, <-- Checked to ensure this was true
"experimentalDecorators": true,
"sourceMap": true,
"declaration": true,
"outDir": "./dist"
},
"files": [
"typings/index.d.ts",
"index.ts"
],
"exclude": [
"node_modules",
"dist"
]
}
Based on these items, or something else, what am I missing to get this working? Thanks!
Edit: sample.*.d.ts files (as default after installation)
// sample.component.d.ts
export declare class SampleComponent {
constructor();
}
// sample.directive.d.ts
import { ElementRef } from '#angular/core';
export declare class SampleDirective {
private el;
constructor(el: ElementRef);
}
Edit 2
So I tried symlinking the dist directory (my-test-library/dist) to the root of node_modules and importing the module from there and it worked fine.
Is there a way to, using npm link, only import the dist directory (at the root)?
I also don't understand why updating my original import to import { SampleModule } from 'my-test-library/dist'; does not work?
Did you try to run watch on your code (something like "npm run watch")? That would give a better error message.
Assuming this is your index.ts file or similar to this (https://github.com/jvandemo/generator-angular2-library/blob/master/generators/app/templates/index.ts) What I am guessing is that either your module is not being exported properly or there are some circular dependencies among your exports. First, try changing the following four lines in your index.ts from:
export * from './src/sample.component';
export * from './src/sample.directive';
export * from './src/sample.pipe';
export * from './src/sample.service';
to
export {SampleComponent} from "./src/sample.component";
export {SampleDirective} from "./src/sample.directive";
export {SamplePipe} from "./src/sample.pipe";
export {SampleService} from "./src/sample.service";
If that doesnt work, then try changing the order of your exports. If still no luck, then please trying sharing the whole folder somewhere. Thanks,
In your file listing I do not see a sample.module.ts, only a component, directive, pipe and service. If you do not have a file with the #ngModule decorator which imports/provides these, then you are not truly importing a SampleModule.
the file should look something like this:
sample.modeule.ts
import { NgModule } from '#angular/core';
import { SampleDirective } from './sample.directive';
import { SampleComponent } from '../sample.component';
import { SamplePipe } from './sample.pipe';
import { SampleService } from './sample.service';
#NgModule({
imports: [ ],
declarations: [
SampleDirective,
SampleComponent,
SamplePipe
],
providers:[SampleService],
exports: [
SampleDirective,
SampleComponent,
SamplePipe
]
})
export class DayModule { }
I'm trying test my React component with Jest + Enzyme, but when my component has SASS file (scss), is occurring SyntaxError.
This is my SASS file content:
.user-box {
width: 50px;
height: 50px;
}
And I just import that in my component:
import React from 'react';
import './userBox.scss';
class MyComponent extends React.Component {
render() {
const style = {
borderRadius: '99px'
};
return (
<div>Hello World</div>
);
}
}
export default MyComponent;
Following error message of my test:
If I comment the import './userBox.scss';, test will be okey.
How to can I test React component with Jest + ‵Enzyme` when has style imported
If you have Babel in your stack, you can fix this in the right way using babel-jest
Just do npm i --save-dev babel-jest and in your jest settings file add:
"moduleNameMapper": {
"^.+\\.(css|less|scss)$": "babel-jest"
}
You have do define a mock for this kind of file by define moduleNameMapper in your jest settings.
We are using identity-obj-proxy. So install it with
npm install identity-obj-proxy --save-dev
and add it your jest setting:
"moduleNameMapper": {
"^.+\\.(css|less|scss)$": "identity-obj-proxy"
}
The following information wasn't available before, so I made a pull request on facebook/jest and it was merged.
I wanted to stub style imported in modules, something like:
// module.js
import Style from '#/path/to/style.scss';
import App from './App';
So I created a style stub file:
// test/unit/stubs/style.js
module.exports = '.style-stub{color:red;}';
After messing around with the following jest.conf.js:
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1', // '#' alias
'^.*\\.scss$': '<rootDir>/test/unit/stubs/style.js',
}
I found that the moduleNameMapper ordering is important. The # alias rule was resolving before my .scss rule, so the style file was loaded as a normal module and would crash the test.
The solution is to put specific rules first.
moduleNameMapper: {
'^.*\\.scss$': '<rootDir>/test/unit/stubs/style.js',
'^#/(.*)$': '<rootDir>/src/$1',
}
I have been searching for a while for a solution to a similar problem and I kept coming across the solution above.
I didn't seem to work for me at first but I realised that Jest was simply ignoring anything I added to "jest" in package.json. My setup includes a jest.config.js file. I found that if I added "moduleNameMapper" there, it worked. So now my jest.test.config.js looks something like this:
module.exports = {
setupFiles: ["<rootDir>/testSetup.js"],
moduleNameMapper: {
"^.+\\.(css|scss)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/fileMocks.js"
}
};