Jest Call retries were exceeded - javascript

I have error in the following below test. My node version is : v12.10.0. is there any alternative of setTimeout?
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
The Error log is as
Call retries were exceeded
at ChildProcessWorker.initialize (../../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:230:21)

just add jest.useFakeTimers(); after your imports
...
jest.useFakeTimers();
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
it works in my code

In my case, the actual problem was with the promise handling.
I got the same issue when I was running all my test cases in one go with the jest.
Solution:
Try running one test separately then see what error is coming.
I got the below error after running one problematic test separately where earlier I was getting the Call retries were exceeded:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read property 'code' of undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
With this, I was sure that the problem is with the catch block and when I added it in the async service API function then the test case worked perfectly fine.
Maybe you can also try the same and see if it works for you or not.
I am using the below config:
node: 15.13.0
npm: 7.8.0
jest: 26.6.3

Try running npm doctor using the latest npm version. It's a great tool and it helped me diagnose permission and ownership issues right away.
Takeaway:
Verify File/Folder Permissions & Ownership

Encountered same error when updating the vue-jest version to below listed versions
#vue/vue3-jest: ^27.0.0-alpha.4
#vue/cli-plugin-unit-jest: ~5.0.0,
node: v17.9.0 or v16.14.2
Error disappeared, once downgraded it to node version v14.x.x
Hunch is - the latest node versions are not compatible with the dependencies.

I was able to run the test's successfully doing the following;
Install npm i -D jest-canvas-mock
Update the jest.config.ts file to have:
export default {
...
testEnvironment: "jsdom",
setupFiles: ["jest-canvas-mock"],
}

Related

Node Commander.js catching options passed to Mocha when running tests

I've recently introduced commander.js to a project and use it in various scripts to parse CLI arguments. I'll give one example of where it's been used:
const { program } = require('commander');
program
.description('Import customers and accounts')
.argument('[filePath]', 'Path to JSON file containing customers and accounts', `${path.resolve(__dirname)}/data/customers.json`)
.action(filePath => {
importCustomersAndAccounts(filePath)
.catch((e) => {
console.log(e);
process.exit();
})
.finally(() => process.exit());
})
program.parse();
This script itself isn't the issue, it works fine when run from the CLI. The issue happens when I run tests that use this same script. I have the test script setup in package.json as follows:
"test": "NODE_ENV=TESTING mocha --exit --require tests/setup.js 'tests/src/**/*.spec.js' 'tests/scripts/**/*.spec.js'"
When I run the tests, I immediately get this error:
error: unknown option '--exit'
Which is being thrown by commander, not mocha. So this option getting passed to mocha when running npm run test is getting to the script itself. I've confirmed this is what's happening, because when I chained .option('--exit') after the .description() in the commander code above, it then failed with
error: unknown option '--require'
So it's reaching the next option passed to mocha and then failing on whichever option is not defined in the script. How can I prevent these options from reaching the script itself and get them to simply be parsed by mocha?

closing open handles detected by jest

i am writting tests for a node application which uses bull to process background jobs.
the test seems to be passing and working as expected but i am seeing the following error message
Jest has detected the following
8 open handles potentially keeping
Jest from exiting:
the log points to specifically this line and other similar statements.
const csvExportsQueue = ['test', 'development'].includes(process.env.NODE_ENV) ? new Queue('exports') : new Queue('csv exports', 'redis://redis:6379/13');
I tried to add the below statement to my test but it still gives the same error
afterAll(async () => {
await new Promise(resolve => setTimeout(() => resolve(), 10000)); // avoid jest open handle error
});
any help on how to fix this will be great, thanks.
add "jest --detectOpenHandles" to "test" in package.json to see the openhandles for Debugging
check your db connection (most likely) and close it them with connection.end()

Possible Unhandled Promise Rejection (id: 0): Error: "getLoginData" is read-only

Destructuring from props is not working inside an async function while it's working fine if I use it using this.props.
This is for a react-native app already in production which suddenly started giving this error 2 days back.
I've tried upgrading babel using this
But no success so far.
If I use this.props.getLoginData instead, it works fine
If I use following function, it's erroneous:
yo = async () => { // with async
const { getLoginData } = this.props; // error
};
While the following function works fine:
yo = () => { // without async
const { getLoginData } = this.props;
console.log(getLoginData); // works fine
};
This also works fine:
yo = async () => { // with async
console.log(this.props.getLoginData); // works fine
};
I expect both of the scenarios to run fine.
Please clone and run this repo to reproduce this bug.
Please find the steps to run the project and environment info in README.md.
P.S.: You will find the error in console( Press ⌘⌥I )
It looks like a dependency of babel is the cause of the issue in my case.
When I look in my package-lock.json, and search for plugin-transform-regenerator I see version 7.4.5. Locking the version to 7.4.4 by adding it to my package.json allows me to build without issue.
This problem would have been easier to track down if I was not ignoring my package-lock.json.
In summary,
npm i -E #babel/plugin-transform-regenerator#7.4.4
I've encountered the same problem.
Using babel version 7.4.4 didn't help me, but I've found another solution that worked - wrapping the destructure in try-catch block.
I still don't know why this problem happens though - will update when I do.
________UPDATE_______
Eventually, the solution #makenova offered worked (Thanks man!).
What I had to do is to remove all node modules + package-lock, then run
npm i -E #babel/plugin-transform-regenerator#7.4.4
and after that run
npm i
Before that I've used yarn and it didn't do the trick.
Update:
nicolo-ribaudo fixed the issue here: https://github.com/facebook/regenerator/pull/377
An alternative solution is to force the regenerator-transform to use ~0.13.0 as suggested by nicolo-ribaudo.
If you are using yarn, add this to your package.json:
"resolutions": {
"regenerator-transform": "~0.13.0"
}
If you are using npm:
Install it as a devDependency
Delete package-lock.json
Re-install dependencies
I've a async function, when destructuring and save const show me error: Possible Unhandled Promise Rejection (id: 0): Error: “userOperations” is read-only , this worked for me (change let by const):
https://github.com/facebook/regenerator/issues/375#issuecomment-527209159

ReferenceError: You are trying to `import` a file after the Jest environment has been torn down

I have a component that makes use of Animated component from react native. I started writing a test case to simulate onPress of a component, which calls a function that has Animated.timing in it, and setState.
running jest works fine, but the tests never stops running, and one unrelated test case that I've written before never seem to pass now (which passed before).
running jest --watch, I get this error:
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
at Function.bezier (node_modules/react-native/Libraries/Animated/src/Easing.js:113:21)
at ease (node_modules/react-native/Libraries/Animated/src/Easing.js:34:24)
at TimingAnimation._easing (node_modules/react-native/Libraries/Animated/src/Easing.js:133:18)
at TimingAnimation.onUpdate (node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js:107:45)
RUNS src/__tests__/SlideDownMenu.test.js
/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:114
return _bezier(x1, y1, x2, y2);
^
TypeError: _bezier is not a function
at Function.bezier (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:224:12)
at ease (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:94:21)
at TimingAnimation._easing (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:255:16)
at TimingAnimation.onUpdate (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js:138:14)
at ontimeout (timers.js:386:11)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
Link to repl
https://repl.it/repls/PartialGrimyMetadata
Environment:
OS: Linux 4.14
Node: 6.14.2
Yarn: 1.7.0
npm: 3.10.10
Watchman: Not Found
Xcode: N/A
Android Studio: Not Found
OK, found a solution.
Should use jest.useFakeTimers()
Note: Put the code above just after import section in your test file.
jest.useFakeTimers()
With above it's extremely important to understand this
jest.useFakeTimers() mocks out setTimeout and other timer functions with mock functions.
If running multiple tests inside of one file or describe block, jest.useFakeTimers(); can be called before each test manually or with a setup function such as beforeEach.
Not doing so will result in the internal usage counter not being reset.
Add "testEnvironment": "jsdom" into jest key in package.json or jest.config.js
"jest": {
"testEnvironment": "jsdom",
"preset": "react-native",
...
taken from: https://stackoverflow.com/a/64567257/728287
I would like to contribute to the answer.
Well let's see the error message
ReferenceError: You are trying to 'import' a file after the Jest environment has been torn down.
Torn down means: Jest already finished running and some part of your code is trying to execute after jest has already finished running the test. This is pretty common on Javascript due to its asynchronous nature.
Sometimes it happens after a promise callback was executed. For example:
import { someProcess } from 'a-library'
task.job().then(result => {
someProcess(result)
})
In the example above, the code imports someProcess from a-library.
If the method job from the task object takes longer than the jest execution, its callback (then() invocation) will run outside jest because jest has already finished running the test. Therefore when someProcess gets executed it will be loaded from a-library so jest will complain that you are trying to load a library after jest has been torn down.
The answer marked as the solution is partially right because calling jest.useFakeTimers() will prevent your code to wait the n seconds you supposed to wait when calling setTime or similar, making your code artificially synchronous.
Making your test await those method calls would help you understand better where the error is being introduced.
The code that worked for me was
describe("Some test set", () => {
let heavyWorkingService = library.workingService();
// We are marking the test function call as async
test(("Name of the test"), async () => {
// we are awaiting heavyWorkingService to finish its job
await heavyWorkingService("some data")
})
})
In my real scenario, my code was getting data from firebase and because I'm not using mocks for this test, it was trying to import firebase after the .get() data read returned. Marking the test as async and calling the method with the await keyword solved my problem
Of course there are a lot of ways to deal with this error, just wanted you to know the true reason behind this error so you can work in the right solution for your tests!
I am using #testing-library/react-native, so what I did is to cleanup in the setup file.
// jest.setup.js
import { cleanup } from '#testing-library/react-native';
afterEach(cleanup);
add the below lines at the very end of the jest test file,
after all, tests are written.
afterAll(() => {
mongoose.connection.close()
})
and also just run a single test file at a time, for example,
> jest --verbose --runInBand -- filename.test.js
None of above works for me. My solution is to add to jest-setup.js file this code:
import { Animated } from 'react-native';
Animated.timing = () => ({
start: () => jest.fn(),
});
Don't forget to include this file to your package.json jest configuration:
...
"jest": {
...,
"setupFiles": [
"<rootDir>/src/tests/jest-setup.js"
]
},
...
I hope it will help anybody
jest.useFakeTimers was not an option for me since it brakes the execution of other libraries I am using.
My workaround was to simply add a delay after each test, so that any async operation has time to complete before Jest environment is torn down:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
describe('Test suite', () => {
// Give time to any async operation to complete after each test
afterEach(async () => {
await sleep(2000);
});
// Also close any pending connection (or related) if any
afterAll(async () => {
await closeConnections();
});
it('My test', async () => {
// Test...
});
});
Of course the delay time must be tuned for your application.
I was getting this issue while testing Apollo with react-native-testing-library.
In this case there were two queries, in a parent and child component. The parent query needed to resolve before the child rendered and fired its query.
The solution was to run the wait() function twice rather than just once. I assume the double-fire is necessary to ensure both queries run. The error message is very opaque though.
test("...", () => {
const rr = render(...);
await wait();
await wait(); // Child query must also run
expect(...);
}
// Wait a tick so the query runs
// https://www.apollographql.com/docs/react/development-testing/testing/#testing-final-state
export async function wait(ms = 0) {
await act(async () => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
});
}
I'm using #testing-library/react-native. On my test case, I need to call render(<MyComponent/>) twice so I needed to add afterEach(cleanup) that way it fixed the issue.
In my case i was using typeorm and put that code inside my jest.setup.ts
afterAll(async () => {
const connection = getConnection();
connection.close();
});
Just to add my bit to the discussion... Double-check if you have any asynchronous code in your test case.
My case was basically a lack of attention, see:
it('should not allow click', async () => {
const page = await newE2EPage();
await page.setContent(`<my-button disabled></my-button>`);
const component = await page.find('my-button');
// WRONG ! ! ! (since click() is async)
component.click();
// ✅ Correct
await component.click()
...
});
The error message isn't that straightforward to understand (at least it wasn't for me). I hope this helps someone!
I tried adding jest.useFakeTimers() inside my beforeEach() method but it didn't resolve the issue for me.
This jest.mock() call above my test cases was the culprit for me:
jest.mock('axios', () => ({
post: () => Promise.resolve({ data: 'data' }),
}));
Removing it resolved my issue.
Hope this helps someone.
Adding "testEnvironment": "jsdom" in package.json didn't helped in my case.
Then I added in the test file under all imports:
jest.useFakeTimers();
and inside describe but above the first test:
beforeEach(() => {
jest.resetAllMocks();
});
and that solved the problem for me.
IN THIS CASE THE ERROR IS SELF EXPLANATORY:
Maybe a bit late to the party but I just want to help whoever is still struggling with this. As the error says, the problem is that some part of your code is trying to import a module after the test has finished. Check the following code:
it('should do something', () => {
someAsyncFuntion(); // We arent awaiting this function so the test ends before execution
});
const someAsyncFunction = async () => {
const {getByPlaceholderText} = render(<SomeComponent />)
getByPlaceholderText('Some placeholder text')
}
With this code the error will be fired, but why? If we check the code for getByPlaceholderText we will see that it is dynamically importing the TextInput component:
const getTextInputNodeByPlaceholderText = (node, placeholder, options = {}) => {
try {
const {
TextInput
} = require('react-native'); // <--- Here we have our import
const {
exact,
normalizer
} = options;
return (0, _filterNodeByType.filterNodeByType)(node, TextInput) && (0, _matches.matches)(placeholder, node.props.placeholder, normalizer, exact);
} catch (error) {
throw (0, _errors.createLibraryNotSupportedError)(error);
}
};
So as the error says, we are trying to import a module after the test has finished.
Add this into your jest.config.js
timers: "fake",
This helps me to resolve this problem.
My jest.config.js file now looks this way
module.exports = {
preset: "react-native",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
transformIgnorePatterns: [
"node_modules/(?!(#react-native|react-native|react-native-vector-icons)/)",
],
timers: "fake",
};
In the latest versions of Jest use this one
import type { Config } from "jest";
const config: Config = {
preset: "react-native",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
testPathIgnorePatterns: [
"/node_modules/",
"<rootDir>/template",
"Libraries/Renderer",
"RNTester/e2e",
],
transformIgnorePatterns: [
"node_modules/(?!(#react-native|react-native|react-native-vector-icons)/)",
],
fakeTimers: {
enableGlobally: true,
},
verbose: true,
};
export default config;
My project is with ReactNative and TypeScipt
and my Jest config by default is in package.json.
To solve this issue i just had to add "timers": "fake"
"jest": {
"timers": "fake",
"preset": "react-native",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]}
The reason why you need this was already explained:
Torn down means: Jest already finished running and some part of your code is trying to execute after jest has already finished running the test. This is pretty common on Javascript due to its asynchronous nature.
There's NO need to add "testEnvironment": "jsdom". As people say above; has no sense with ReactNative.
Using jest.useFakeTimers() on top of code after imports, did not work for me.
I found the below solution here
now at least, I do not see the error now but a warning message appeared at the end saying..
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.
it('your test case', () => {...})
becomes:
it('your test case', async () => {...})
adding async removes the erroring out.
I used jest.useFakeTimers() in beforeEach() method inside test suit of that file
beforeEach(() => {
jest.useFakeTimers();
});
OR
use jest.useFakeTimers() on top of code after imports

"fetch is not found globally and no fetcher passed" when using spacejam in meteor

I'm writing unit tests to check my api. Before I merged my git test branch with my dev branch everything was fine, but then I started to get this error:
App running at: http://localhost:4096/
spacejam: meteor is ready
spacejam: spawning phantomjs
phantomjs: Running tests at http://localhost:4096/local using test-in-console
phantomjs: Error: fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/unfetch.
For example:
import fetch from 'unfetch';
import { createHttpLink } from 'apollo-link-http';
const link = createHttpLink({ uri: '/graphql', fetch: fetch });
Here's a part of my api.test.js file:
describe('GraphQL API for users', () => {
before(() => {
StubCollections.add([Meteor.users]);
StubCollections.stub();
});
after(() => {
StubCollections.restore();
});
it('should do the work', () => {
const x = 'hello';
expect(x).to.be.a('string');
});
});
The funniest thing is that I don't even have graphql in my tests (although, I use it in my meteor package)
Unfortunately, I didn't to find enough information (apart from apollo-link-http docs that has examples, but still puzzles me). I did try to use that example, but it didn't help and I still get the same error
I got the same error importing a npm module doing graphql queries into my React application. The app was compiling but tests were failing since window.fetch is not available in the Node.js runtime.
I solved the problem by installing node-fetch https://www.npmjs.com/package/node-fetch and adding the following declarations to jest.config.js:
const fetch = require('node-fetch')
global.fetch = fetch
global.window = global
global.Headers = fetch.Headers
global.Request = fetch.Request
global.Response = fetch.Response
global.location = { hostname: '' }
Doing so we instruct Jest on how to handle window.fetch when it executes frontend code in the Node.js runtime.
If you're using nodejs do the following:
Install node-fetch
npm install --save node-fetch
Add the line below to index.js:
global.fetch = require('node-fetch');
The problem is this: fetch is defined when you are in the browser, and is available as fetch, or even window.fetch
In the server it is not defined, and either needs to be imported explicity, or a polyfill like https://www.npmjs.com/package/unfetch (as suggested in the error message) needs to be imported by your test code to make the problem go away.

Categories