I am trying to write a really simple test from vue documentation inside my Project.
I can run tests with jest in my project, but as soon as i am trying to mock axios request with jest, i have this error :
FAIL tests/unit/test.spec.js
● Test suite failed to run
Cannot find module '#jest/globals' from 'test.spec.js'
14 | })
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:259:17)
at _getJestObj (tests/unit/test.spec.js:16:7)
at Object.<anonymous> (tests/unit/test.spec.js:3:1)
Here is my Foo component :
<template>
<button #click="fetchResults">{{ value }}</button>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
value: null
}
},
methods: {
async fetchResults() {
const response = await axios.get('mock/service')
this.value = response.data
}
}
}
</script>
And the test associated :
import { shallowMount } from '#vue/test-utils'
import Foo from './Foo'
jest.mock('axios', () => ({
get: Promise.resolve('value')
}))
it('fetches async when a button is clicked', done => {
const wrapper = shallowMount(Foo)
wrapper.find('button').trigger('click')
wrapper.vm.$nextTick(() => {
expect(wrapper.text()).toBe('value')
done()
})
}
Any help would be appreciated :)
Thanks guys !
Assuming that you are also using babel-jest, make sure you have both versions of jest and babel-jest set to same numer (24, 26` etc.). I had the same problem and it was because the package versions were not in sync.
If you're using npm 7+, then peer dependencies are automatically installed and you could end up with two different versions of babel-jest used simultaneously. You can disable that behavior by adding
legacy-peer-deps=true
into .npmrc file.
In my case, this error happens in babel-jest#26.0.1. After downgrade to babel-jest#21.2.0, problem disappear.
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";
Here is my react component:
import { sendAnalytics } from 'analytics';
class MyComponent extends React.Component {
myMethod() {
console.log('do something!');
}
render() {
return (
<Button
onClick={submitAnalytics({name: 'foo'}).finally(this.myMethod())}
dataset={{"data-id": "button"}}
> Send Analytics
</Button>
}
)
}
}
And my test is like so:
import * as analytics from 'analytics';
jest.mock('analytics');
describe('Analytics', () => {
it('Should call analytics when button is clicked', () => {
analytics.submitAnalytics.mockResolvedValue(Promise.resolve(true));
const tree = ReactTestRenderer.create(<MyComponent />);
// Actual implementation of following 3 lines is slightly different.
const button = tree.root.findByProps({"data-id": "button"});
button.props.onClick();
expect(analytics.submitAnalytics).toHaveBeenCalled();
});
});
I tried several different mocking strategies like:
analytics.submitAnalytics.mockImplementation(() => {
return Promise.resolve(true)
});
Nothing seems to work out. I keep getting the following error:
TypeError: (0 , analytics.submitAnalytics)(...).finally is not a function.
I don't know why. Any help appreciated.
Please let me know if you need any more contextual code.
Importing #babel/polyfill before the test also solve this problem
import '#babel/polyfill';
// Your tests...
Upgrading my node version from
v8.10.0
to
v10.19.0
Resolved this error.
Looking at the Browser Compatibility chart on MDN it looks like .finally() is not supported in Node until 10.0.0
import '#babel/polyfill'; worked for me, but is deprecated since babel 7.4.
Instead, import this works fine as well:
import "core-js/stable";
import "regenerator-runtime/runtime";
eventually, I just updated node version (from 8.10.2 to 12.16.1)
I figured it out folks! Here's what was to be done:
analytics.submitPayload = jest.fn().mockImplementation(() => {
return {
finally: () => {
return true;
}
};
});
I don't know if this is right or wrong, but it works. Please let me know if there's a better way to do it.
I faced same challenge.
Reason- Jest runs in Node enviroment,and "Finally" is supported from Node version- 10.0.0. But my Jenkins versions was 8.x so As a quick fix you can remove finally from code. Later we can upgrade local and remote server version.
Below is MDN link-
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
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 have seen questions referring to the mocking of default exports with jest around here, but I don't think this has already been asked:
When mocking the default export of a dependency of a module that is being tested, the tests suite fails to run if the module imports the dependency with the ES6 import statement, stating TypeError: (0 , _dependency.default) is not a function It succeeds, however, if the module uses a require().default call instead.
In my understanding, import module from location directly translates to const module = require(location).default, so I am very confused why this is happening. I'd rather keep my code style consistent and not use the require call in the original module.
Is there a way to do it?
Test file with mock:
import './modules.js';
import dependency from './dependency';
jest.mock('./dependency', () => {
return {
default: jest.fn()
};
});
// This is what I would eventually like to call
it('calls the mocked function', () => {
expect(dependency).toHaveBeenCalled();
});
Dependency.js
export default () => console.log('do something');
module.js (not working)
import dependency from './dependency.js';
dependency();
module.js (working)
const dependency = require('./dependency.js').default;
dependency();
You can use either es6 import or require js to import your js files in your jest tests.
When using es6 import you should know that jest is trying to resolve all the dependencies and also calls the constructor for the class that you are importing. During this step, you cannot mock it. The dependency has to be successfully resolved, and then you can proceed with mocks.
I should also add that as can be seen here jest by default hoists any jest.mocks to the top of the file so the order in which you place your imports does not really matter.
Your problem though is different. Your mock function assumes that you have included your js file using require js.
jest.mock('./dependecy', () => {
return {
default: jest.fn()
};
});
When you import a file using require js, this is the structure it has:
So assuming I have imported my class called "Test" using require js, and it has method called "doSomething" I could call it in my test by doing something like:
const test = require('../Test');
test.default.doSomething();
When importing it using es6 import, you should do it differently though. Using the same example:
import Test from '../Test';
Test.doSomething();
EDIT: If you want to use es6 import change your mock function to:
jest.mock('./dependecy', () => jest.fn());
the short answer for ES module if you want to use
import dependency from 'dependency'
jest.mock('dependency', () => ({
...jest.requireActual('dependency'),
__esModule: true,
default: jest.fn(),
}))
Have you tried something like this? I was dealing with the default export mocking for months until I found this.
jest.mock('./dependency', () => () => jest.fn());
The idea behind this line is that you are exporting a module that is a function. So you need to let Jest knows that it has to mock all your ./dependency file as a function, that returns a jest.fn()
I want to unit test a function in my application that calls and updates a Firebase reference. The problem I am facing is that when I try to run the test and import the file that contains the function, I get the following error SyntaxError: Unexpected token u in JSON at position 0 which points to the line in my function file that imports my reference to Firebase.
I am using Webpack and Babel on this project, so I tried setting a resolve.alias in the webpack.config file which worked when the application was running, but did not work when I ran npm test. At this point I'm at a loss as to how I can mock out the Firebase reference so I can test the other functions of the function. Here's some sample code:
constants/index.js
import firebase from 'firebase';
const firebaseConfig = JSON.parse(unescape(`${config.FIREBASE_CONFIG}`));
const mainApp = firebase.initializeApp(firebaseConfig);
export const ref = mainApp.database().ref();
actions/settings.js
import * as actions from './';
import { ref } from '../constants';
export const updateSetting = (e, value) =>
(dispatch) => {
ref.child('setting')
.set(value)
.then(() => {
dispatch(actions.confirmFBSave());
})
.catch((err) => {
dispatch(actions.failFBSave({ text: err.code }));
});
};
What testing framework are you using Qunit, jasmine, mocha? With AngularFire and Angular it is much easier because you can pass a mock class in at DI, but I have also tested non angular js for server side. Then I used Sinon to get mock initializeApp and return a Mock firebase app.
You could also try https://github.com/thlorenz/proxyquire I didn't need to go that far, but I have seen it suggested. That way you are essentially intercepting the import and swap it out for something you can test with.