I'm having a great deal of trouble using Enzyme and Mocha to test my React project. I have a test like this:
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import { ChipInput} from '../client/components/Chips';
describe('<ChipInput />', _ => {
it('rocks', done => {
done();
});
});
And when ChipInput gets imported, that file imports something with an absolute path, e.g. /lib/collections/tags, and then Mocha errors out because it apparently only does relative paths. How do I get this working?
EDIT:
The actual error:
Error: Cannot find module '/lib/collections/tags'
This happens because /tests/ChipInput-test.js imports the ChipInput component from /client/components/Chips/index.js, which has the following lines:
import React from 'react';
import {
MapsLocalOffer as TagIcon,
ImageRemoveRedEye as InsightIcon,
EditorInsertChart as TestIcon,
SocialPerson as UserIcon,
} from 'material-ui/svg-icons';
import { Tag } from '/lib/collections/tags'; // error thrown here
import { Insight } from '/lib/collections/insights';
// import { Test } from '/lib/collections/tests';
import Chip from './Chip';
import ChipDisplay from './ChipDisplay';
import ChipInput from './ChipInput';
import * as chipTypes from './chip-types';
To anyone hitting here from google, while ffxsam's answer will work, there are many ways to accomplish this. Node's require allows for a base to be set either via environment variable or programmatically, allowing for simple absolute paths that don't require the leading slash (require("my/module"); vs require("/my/module");).
I use gulp as a taskrunner, so my preferred technique is to use app-module-path to do the following at the top of my gulpfile (this will work anywhere, so long as you haven't encountered any absolute requires yet):
require('babel-core/register'); //for mocha to use es6
require('app-module-path').addPath(__dirname + '/src'); //set root path
//I also use webpack to pull in other extensions, so I
//want mocha to noop out on them
require.extensions['.css'] = _.noop;
require.extensions['.scss'] = _.noop;
require.extensions['.png'] = _.noop;
require.extensions['.jpg'] = _.noop;
require.extensions['.jpeg'] = _.noop;
require.extensions['.gif'] = _.noop;
For a more complete rundown, check out this gist by github user branneman: https://gist.github.com/branneman/8048520
This has been awhile, but I want to share my solution here, just in case, all solutions above don't work in your specific situation. I was looking for a solution to fix our unit test, which failed "Error: Cannot find module 'components/shared/xyz', our 'components' folder is under 'client/src' folder, so I came up with the following solution which works for us.
npm install babel-plugin-module-resolver --save-dev
{
'plugins': [
'babel-plugin-module-resolver',
{ 'root': ['client/src'] }
]
}
Here's the solution, nice and simple!
https://github.com/mantrajs/babel-root-slash-import
Basically, install said package:
npm install babel-root-slash-import --save-dev
Add the plugin to .babelrc:
{
"plugins": [
"babel-root-slash-import"
]
}
And it's good to go.
Related
I've got a file called "globalHelper.js" like this:
exports.myMethod = (data) => {
// method here
}
exports.myOtherMethod = () => { ... }
and so on...
I import my Helper in other files like this:
import helper from "../Helper/globalHelper";
Now there is the problem:
In the past, everything worked with that when running my build-script:
"build": "GENERATE_SOURCEMAP=false react-scripts build"
but for some reason, when I run "npm run build", I get the error:
Attempted import error: '../Helper/globalHelper' does not contain a default export (imported as 'helper')
However, when I simply start my development server (npm start), everything works just fine.
I already tried to import like import { helper } from "../Helper/globalHelper";, but that did not work either.
Does someone know how to solve that?
try exporting like this with ES6 syntax
export const myOtherMethod = () => { ... }
then
import { myOtherMethod } from '...your file'
The method you are using exports.functionName is CJS. you need to use require to get the methods.
The CommonJS (CJS) format is used in Node.js and uses require and
module.exports to define dependencies and modules. The npm ecosystem
is built upon this format.
If you want to use module method you can do this.
export { myOtherMethod1, myOtherMethod2 }
then you import like this.
import * as Module from '....file name'
Since you've not export default you should import the function with {} like :
import {helper} from "../Helper/globalHelper";
I have been working on a React Typescript repo and have been running into an annoying issue where in jest is not able to resolve imports relative to root dir.
Cannot find module '~lib/dates' from 'utils.ts'
And this how the import looks like in the component / utils
import { abc } from '~lib/dates'; // this fails to run
If I change this to a relative path jest test runs works as expected
import { abc } from '../../lib/dates'; // this runs as expected
The same path work for some other directories and I am a bit stumped
import { xyz } from '~components/home/constants'; // jest resolves it
import { abc } from '~lib/dates'; // ERR
I tried including moduleNameWrapper in the jestConfig to see if it jest can resolve the imports correctly but it did not help.
package.json
"jest": {
...
"moduleNameWrapper": {
"^~(.*)$": "<rootDir>/src/$1"
}
}
I could for sure update the VS code setting so that auto imports are resolved relatively to the file and not with the root dir but this has been bugging me for a while. It would be great if anyone has any pointers on how best to resolve this.
I am on a monorepo with the following directory structure
repo
server
client
src
components
lib
utils
package.json
Your implementation looks right. But it looks like the option moduleNameWrapper was the wrong option, it's supposed to be moduleNameMapper.
I also have an example as same as you which also uses babel as transplier, it works fine as I added moduleNameMapper. Here is the my example:
Jest configuration:
https://github.com/tmhao2005/lerna-demo/blob/master/packages/share/jest.config.js
Here is the file for testing:
https://github.com/tmhao2005/lerna-demo/blob/master/packages/helper/src/index.ts
https://github.com/tmhao2005/lerna-demo/blob/master/packages/helper/src/index.test.ts
forget the ~ character;
first define root directory to jest (i.e. src/);
then import your stuff from that root directory; (e.g. import { abc } from 'lib/dates')
by the way you can always import your stuff from default root without any configuration like this: import { abc } from 'src/lib/dates'
further read if you are using create-react-app jest absolute import
I want to use https://github.com/gdsestimating/dxf-parser in my project. When i import in like:
import { DxfParser } from 'dxf-parser';
and than call:
new DxfParser()
i get an error:
TypeError: dxf_parser__WEBPACK_IMPORTED_MODULE_3__ is not a
constructor
What would be the correct way to use the DxfParser in angular? I want to do the same in angular as the jaascript example on projects site:
var parser = new DxfParser();
try {
var dxf = parser.parseSync(fileText);
}catch(err) {
return console.error(err.stack);
}
thanks a lot!
Like the readme of the github states, did you install DxfParser?
npm install dxf-parser
You might also need to install the types for typescript like so:
npm install #types/dxf-parser
Since installing does not seem to be the problem I tried it myself. Doing the import like you did does not work. I looked into the code and it seems that DxfParser is a default export. So if you do:
import DxfParser from "dxf-parser";
It should be working.
More information on exports can be found here
I am trying to manually include the #material/drawer npm package into my Ember app. I tried following this guide but I'm running into some weird errors in my Chrome dev console:
Uncaught SyntaxError: Unexpected token *
Uncaught ReferenceError: define is not defined
The first is from the imported node_modules/#material/drawer/index.js file and the second is from my generated shim.
My component code:
import Component from '#ember/component';
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
export default Component.extend({
init() {
this._super(...arguments);
const drawer = new MDCTemporaryDrawer(document.querySelector('.mdc-drawer--temporary'));
document.querySelector('.menu').addEventListener('click', () => drawer.open = true);
}
});
In my ember-cli-build.js:
app.import('node_modules/#material/drawer/index.js');
app.import('vendor/shims/#material/drawer.js');
My generated shim:
(function() {
function vendorModule() {
'use strict';
return {
'default': self['#material/drawer'],
__esModule: true,
};
}
define('#material/drawer', [], vendorModule);
})();
What exactly am I doing wrong? It almost seems as though raw ES6 code got imported rather than compiled into my JS build output.
I also read this SO post but there are too many answers and I'm not sure which to do. It seems this specific answer is what I'm trying to do but not verbatim enough.
Creating a shim only ensures that ember-cli gets an AMD module, which you then can import in your app files.
If the npm package needs a build or transpiling step beforhand, this won't work.
You need a way to get the package build within the ember-cli build pipeline.
Luckily there are addons which can take care of this for you: ember-auto-import and ember-cli-cjs-transform.
You may have also heard of ember-browserify, which does the same thing, but it's deprectaed in favor of ember-auto-import.
I'd suggest you try ember-auto-import:
ember install ember-auto-import
You then should be able to import as you tried:
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
No shim or app.import needed, as ember-auto-import will take care of this for you.
I have some JavaScript modules which consume and declare globals. I'm aware that this is an anti-pattern, but it's a stopgap solution: until our dependencies come around to publishing their own ES module versions, we destructure them from globals. Here's what we do with Redux, as an example.
// Example: instead of
import createStore from '../path/to/redux.js';
// we do
const {createStore} = Redux;
This works a treat in the browser, and when the dependencies update it will be simple to refactor, however, testing in node with mocha is a different story:
// myReducer.test.mjs
import reducer from '../../src/redux-modules/myReducer';
import initialState from '../../src/redux-modules/myReducer';
export default function videosReducerTests() {
assert('reducer', function() {
it('should return initial state by default', function() {
reducer({}, {}).should.equal(initialState);
});
});
}
I've installed #std/esm to help node work with es modules, and set up my package.json with the following:
"devDependencies": {
"#std/esm": "^0.14.0",
},
"#std/esm":"js",
"scripts": {
"redux-test": "node -r #std/esm test/redux/index.mjs",
}
The result of running yarn redux-test is
ReferenceError: Redux is not defined
I've tried mocking the namespaces I need with global.Redux = {createStore: Function} etc. at the top of my test files, but those are all ignored, since imports are 'hoisted'.
Any tips on how to get around this block?
You might just stick with importing the full redux. It's small enough and may simplify browser/node things.