How to solve issue in jest unit test? - javascript

I have a unit test for a ReactJs/Typescript project that has a reference to a module called nock.js, and using jest:
import nock from 'nock'
...
afterEach(() => {
nock.cleanAll();
})
When I run the test I get an error in the .cleanAll statement:
TypeError: nock_1.default is not a function
However when I change the import statement to :
var nock = require('nock');
The issue is solved. How can I still use import instead of require ? Is this an issue with the jest configuration? This is the config:
"jest": {
"transform": {
"^.+\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"testRegex": "/__tests__/.*\\.(ts|tsx|js)$"
},

If a module has a default export, you can use:
import nock from 'nock'
But if it doesn't have a default export, you'll need to use:
import * as nock from 'nock'

I met the same exact issue, and fixed it by adding the following config to my tsconfig.json:
{
...
"esModuleInterop": true
...
}

Related

jest - Unexpected token 'export' for importing external library

I am going to test below component
WalletButton.jsx
import React from 'react';
import { WalletDialogButton } from "#solana/wallet-adapter-material-ui";
function WalletButton() {
return (
<WalletDialogButton>
{"CONNECT"}
</WalletDialogButton>
);
}
export default WalletButton;
The test case is below:
wallet-button.test.js
import {shallow} from "enzyme"
import React from 'react'
import WalletButton from "./WalletButton";
it('render WalletButton Component', () => {
expect(shallow(<WalletButton/>)).toMatchSnapshot();
})
When I run npm test, it shows error
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/Users/CCCC/Desktop/SourceTree/my-project/node_modules/#solana/wallet-adapter-material-ui/lib/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export * from './useWalletDialog';
I attempt to add
transformIgnorePatterns: [
"node_modules/(?!#solana/wallet-adapter-material-ui)",
]
in jest.config.js but still not working.
How to fix it?
jest.config.js
module.exports = {
moduleDirectories: ["node_modules", "src"],
moduleNameMapper: {
"^#/(.*)$": "<rootDir>/src/$1",
"\\.(css|scss)$": "identity-obj-proxy",
},
transform: {
"^.+\\.(js|jsx)$": "babel-jest",
".+\\.(png|jpg|svg|ttf|woff|woff2)$": "jest-transform-stub",
},
transformIgnorePatterns: [
"node_modules/(?!#solana/wallet-adapter-material-ui)",
],
setupFilesAfterEnv: ["<rootDir>/src/setupTests.js"],
snapshotSerializers: ["enzyme-to-json/serializer"],
};
Update 1
babelrc
{
"presets": [
"#babel/preset-env",
["#babel/preset-react", { "runtime": "automatic" }]
]
}

Jest - cannot find module

I have the following test:
jest.mock('#my-company/my-package/dist/browser');
import { broadcast } from '#my-company/my-package/dist/browser';
...
The file it is importing looks something like this within the node_modules folder:
import someFunction from '#my-company/some-other-package';
...
This is throwing the following error message when I run the test:
Cannot find module '#my-company/some-other-package' from 'browser.js'
Why would I be getting this error?
I have been going through my jest config file and can't spot anything that might be wrong. Here is the config file:
module.exports = {
testPathIgnorePatterns: [
'/node_modules/',
'/bower_components/',
'/cypress/',
'/test/', // test directory contains mocha and chai tests for now
],
transform: {
'.(js|jsx)': '#sucrase/jest-plugin',
},
transformIgnorePatterns: [`node_modules/(?!#my-company/my-package)`],
resolver: '#my-company/jest-bower-resolver',
setupFilesAfterEnv: ['<rootDir>/test/setup-tests.js'],
moduleDirectories: ['node_modules', 'bower_components', "<rootDir>"],
collectCoverageFrom: [
'**/*.{js,jsx}',
'!**/*.spec.js',
'!**/test/**',
'!**/test-jest/**',
'!**/cypress/**',
'!**/coverage/**',
'!**/node_modules/**',
'!**/bower_components/**',
'!**/public/**',
],
coverageDirectory: '<rootDir>/coverage/',
};
It is important to note that the package #my-company/my-package must be added to transformIgnorePatterns part of the config otherwise it won't be transpiled
Thanks

Jest mock ES6 module

How can I mock an ES6 module import using Jest?
For example we have the following structure:
// ../store.js
function getData(data) {
return data / 3;
}
export { getData };
// ../myModule.js
import { getData } from './store';
function myModule(param) {
return getData(param) * 4;
}
export { myModule };
// ./myModule.test.js
import { myModule ] from '../myModule';
test('2 x 4 equal 8', () => {
expect(getData(6)).toBe(8);
});
To mock ES2015 modules, your jest config needs to use babel to convert the modules first.
You'll want to yarn add --dev babel-jest babel-preset-env
and then your package.json should look something like this:
"jest": {
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
],
"transform": {
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$",
"^.+\\.module\\.css$"
]
}
Secondly, in your .babelrc you need to specify your environment for test like so:
{
"presets": [
["env", "react"]
],
"env": {
"development": {
"presets": [["env"], "react"]
},
"production": {
"presets": [["env"], "react"]
},
"test": {
"presets": [["env"], "react"]
}
}
}
Once that's done, you can mock a module. For example, make a file called __mocks__/store.js (where the mocks folder is in the same level as your store.js file. Inside of your mocks file, you can do something like
const getData = () => return 42;
export { getData };
and in your myModule.test.js you need this line:
jest.mock('./store');
If you want, you can see a working example from one of my repositories here:
https://github.com/AnilRedshift/linkedINonymous/
If you want make automated test with jest, you have to include before the test/describe the next call
jest.mock('../myModule');
It returns void result from all functions.
Other alternative is mock mixed:
const mock: any = jest.genMockFromModule('../myModule');
mock.getData = jest.fn().mockImplementation(6);
The call to method getData returns 6.

Jest unit testing config with Quasar-Framework 0.15

I had Jest tests working under Quasar version 0.14. Currently some simple tests and all snapshot-tests pass but for some tests I keep getting:
1.
console.error node_modules/vue/dist/vue.common.js:593
[Vue warn]: Error in config.errorHandler: "TypeError: Cannot read property 'form' of undefined"
and 2:
console.error node_modules/vue/dist/vue.common.js:1743
TypeError: Cannot read property 'getters' of undefined
and 3:
console.error node_modules/vue/dist/vue.common.js:593
[Vue warn]: Unknown custom element: <q-page-sticky> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
1 and 2 seem to relate to Jest not recognizing a $v.form and the vuex store within the components.
Any suggestions/ best practices how to get this working? I followed along this, and have these settings:
.babelrc:
{
"presets": [
[ "env", {"modules": false} ],
"stage-2"
],
"plugins": ["transform-runtime"],
"comments": false,
"env": {
"test": {
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
]
],
"plugins": [
[
"module-resolver",
{
"root": [
"./src"
],
"alias": {
"quasar": "quasar-framework/dist/quasar.mat.esm.js",
"^vue$": "vue/dist/vue.common.js"
}
}
]
]
}
}
}
within package.json:
"jest": {
"testMatch": [
"<rootDir>/src/**/?(*.)(spec).js?(x)"
],
"testPathIgnorePatterns": [
"<rootDir>/src/e2e/"
],
"moduleNameMapper": {
"src/components/([^\\.]*).vue$": "<rootDir>/src/components/$1.vue",
"src/components/([^\\.]*)$": "<rootDir>/src/components/$1.js",
"^vue$": "vue/dist/vue.common.js",
"src/([^\\.]*)$": "<rootDir>/src/$1.js",
"src/([^\\.]*).vue$": "<rootDir>/src/$1.vue",
"(.*)/(.*).vue$": "$1/$2.vue",
"(.*)/(.*)/(.*).vue$": "$1/$2/$3.vue"
},
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"collectCoverageFrom": [
"**/*.{vue}"
],
"coverageDirectory": "<rootDir>/src/components/coverage",
"transformIgnorePatterns": [
"node_modules/core-js",
"node_modules/babel-runtime",
"node_modules/lodash",
"node_modules/vue"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"snapshotSerializers": [
"<rootDir>/node_modules/jest-serializer-vue"
]
},
1. The Problem
Your 3rd error occurred because Jest doesn't know what a <q-page-sticky> is. You have to tell it explicitly.
[Vue warn]: Unknown custom element: <q-page-sticky> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
2. The Solution
Its as simple as telling Vue what 'Vuex' is, or what 'vue-router' is. You are probably already familiar with this. The only difference is that we have to use localVue here in the testing environment.
import { shallowMount, createLocalVue } from "#vue/test-utils";
import MyComponent from "#/components/MyComponent";
// I see that you already alias "quasar" in your .babelrc,
// otherwise replace "quasar" with "quasar-framework/dist/quasar.mat.esm.js"
import Quasar, { q-page-sticky } from "quasar";
// or if you are using a lot of Quasar components then do
// import Quasar, * as All from "quasar";
describe("Something Something", () => {
const localVue = createLocalVue();
localVue.use(Quasar, { components: ["q-page-sticky"]});
// or if you are using a lot of Quasar components then do
// localVue.use(Quasar, { components: All, directives: All, plugins: All });
const wrapper = shallowMount(MyComponent, {
localVue,
});
it("works", () => {
expect(wrapper.isVueInstance()).toBe(true);
});
})
3. Reference
The above is a general solution and can be used not just with Quasar framework. You can checkout the following official vue-test-util docs for more information.
Using with Vue Router
Using with Vuex
I had the same warnings (1 and 2). For me, it was using the wrong mount. I used Vue's mount function instead of the one in #vue/test-utils. I don't have the explanation why it works now, but that was it for me.

(!) Unused external imports. 'reduce' imported from external module 'lodash' but never used

I am using rollup to build my library and I have a dependency on lodash.
but when I run rollup to bundle my code, I get this warning.
(!) Unused external imports
reduce imported from external module 'lodash' but never used
A sample of my code is as follow:
import { reduce } from "lodash"
export function someutilityfunction(args) {
return reduce(args,() => {
// do somthing
}, {}) // A generic use case of reduce function
}
the bundled library works fine.
I have even tried using
import * as _ from "lodash"
and lodash-es instead of lodash
but no success.
Here is my rollup.config.js
import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import filesize from 'rollup-plugin-filesize'
import typescript from 'rollup-plugin-typescript2'
import commonjs from 'rollup-plugin-commonjs'
import uglify from 'rollup-plugin-uglify'
let production = (process.env.NODE_ENV == "production")
export default {
input: 'src/index.ts',
output: {
file: 'lib/index.js',
format: 'cjs',
name: 'my-library',
sourcemap: true
},
external: [
'rxjs',
'axios',
'lodash'
],
plugins: [
resolve(),
typescript({
tsconfigOverride: {
compilerOptions: {
declaration: true,
moduleResolution: "node",
allowSyntheticDefaultImports: true
}
},
// verbosity: 3,
clean: true,
rollupCommonJSResolveHack: true,
abortOnError: false,
typescript: require('typescript'),
}),
commonjs(),
babel({
exclude: 'node_modules/**'
}),
production && uglify(),
filesize()
],
watch: {
include: 'src/**'
}
};
I have used this rollup config before and it has worked fine, until now.
Am I missing something?
And I know the title of the question can be more generic. feel free to improve the post.
Looks like there is a known issue with the tree-shaking within Rollup and Lodash (also D3 has a similar problem):
https://github.com/rollup/rollup/issues/691

Categories