JEST throws .finally is not a function - javascript

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

Related

VS code turns 'it' into 'hasUncaughtExceptionCaptureCallback'. How to disable this?

I am going through a book on Test Driven Development in React. I've never written JavaScript tests before. The author presents the following Jest code in a file titled calc.test.js:
var add = require('./calc.js')
describe('calculator',function() {
it('add two numbers',function() {
expect(add(1,2)).toEqual(3)
})
})
but VS code automatically translates it to:
const { hasUncaughtExceptionCaptureCallback } = require('process')
const { isTypedArray } = require('util/types')
var add = require('./calc.js')
describe('calculator', function () {
isTypedArray('add two numbers', function () {
hasUncaughtExceptionCaptureCallback(add(1, 2).toEqual(3))
})
})
The author states that his version uses syntax "borrowed from" jasmine. Is that why VS Code changed it? How do I turn this feature off? Jest is installed.
Seems like vscode tries to autocomplete it and expect, and auto imports the modules process and utils/types.
Even though manually importing isn't required per the jest documentation:
In your test files, Jest puts each of these methods and objects into
the global environment. You don't have to require or import anything
to use them. However, if you prefer explicit imports, you can do
import {describe, expect, test} from '#jest/globals'.
You can silence vscode warnings by explicitly importing:
import {describe, expect, test} from '#jest/globals'

Cannot find module '#jest/globals' in a vue test using jest

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.

fastify.setValidatorCompiler is not a function

I have fastify 2.14 installed. I am following the documentation to use custom validation library.
Here's my code:
import fastify from 'fastify';
const app = fastify({});
app.setValidatorCompiler(({schema}) => data => schema.validate(data)); // setValidatorCompiler is not a function
console.log(app.setValidatorCompiler) // undefined
export default app;
I also tried passing it in the route options and typescript doesn't recognize it as a field.
also setSerializerCompiler is not a function.
It seems like they have wrong documentation versioning.
I was reading version 2.14 documentation and it was for 3-alpha.
Installing the 3-alpha version solved my problem.
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
return ajv.compile(schema)
})
https://www.fastify.io/docs/v3.3.x/Validation-and-Serialization/#validator-compiler

Expect libarary TypeError: expect(...).toInclude is not a function

I'm guessing it's an import error somehow, but I can't seem to figure out how, expect is up to date and I can't get it too run without it saying
libarary TypeError: expect(...).toInclude is not a function
var request = require("supertest");
var {app} = require("./../server.js");
var {Show} = require("./../models/show");
var expect = require('expect');
describe("GET /show/:id", () => {
it("Should include the show name 'Arrow' in the body", (done) => {
request(app)
.get(`/show/${showName}`)
.expect(200)
.expect((res) => {
expect('hello world').toInclude('world')
})
.end(done);
});
})
});
UPDATE:
besides .toMatchObject, you can also use .toHaveProperty
For anyone who used .toInclude to check if an object contains certain fields, the new version is .toMatchObject.
Here is the document reference
The expect library was recently made part of the Jest project - the Jest team changed the API a little, as this answer explains.
The full documentation for expect can now be found here: https://facebook.github.io/jest/docs/en/expect.html
If you are facing similar problem than it can be solved by importing jest-dom in your test file:
import '#testing-library/jest-dom' in your xyz.test.js
Don't forget to install jest-dom in order to use it with jest:
npm i --save-dev #testing-library/jest-dom
Hope it helps.. :)

Jest mocking default exports - require vs import

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()

Categories

Resources