Unexpected reserved word 'yield' when running Jest unit tests - jestjs

I'm using TypeScript and Jest to write unit tests. When I tried to run them, I got the following error messages:
Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
SyntaxError: C:\..\my\file\name.web.spec.ts: Unexpected reserved word 'yield'.
This came from an original TypeScript section like the following:
it("should do things right", () => {
const payload = { ... };
await manager.init(payload);
});

The solution seems obvious in retrospect when looking at the code, but easy to miss. I just simply needed to make the function async.
it("should do things right", async () => {
const payload = { ... };
await manager.init(payload);
});

Related

How to use a dynamic import in a firebase cloud function using Javascript

How can I make this work without having the pre-deploy linter produce an error? If I disable the linter will it work on the cloud? (It works with my mocha tests).
async function() {
const { ChatGPTAPI } = await import('chatgpt');
}
29:32 error Parsing error: Unexpected token import
✖ 1 problem (1 error, 0 warnings)
Setting type: "module" in package.json produces error with the eslintrc.js

uuid is not a function while using jest

I have the following setup:
// uuid-wrapper.ts
import { v4 as uuidV4 } from 'uuid';
const uuid: () => string = uuidV4;
export { uuid };
// uuid-wrapper.spec.ts
import { uuid } from './uuid-wrapper';
describe('uuid-wrapper', () => {
console.log(uuid());
});
This works fine runtime, but it breaks in test. I'm trying to migrate to Jest 29 and I'm getting the following error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
^^^^^^
SyntaxError: Unexpected token 'export'
From uuid's repo I found a workaround which, after applied and my jest.config.js looks like this:
module.exports = {
moduleNameMapper: {
uuid: require.resolve("uuid"),
},
};
This gives me a different error but I still have no idea what it means:
> jest uuid-wrapper --no-coverage
FAIL src/uuid-wrapper/uuid-wrapper.spec.ts
● Test suite failed to run
TypeError: (0 , uuid_wrapper_1.uuid) is not a function
In fact, any function I export from this file (uuid-wrapper.ts) is not resolved. I have other tests that follow a similar pattern of reexporting packages but only this one breaks. I'm using uuid 9.0.0 and jest 29.1.2.
Edit: After a bit more testing, it turns out that anything I import into the test is "not a function".
uuid ships as an ESModule and Jest should not need to transform it. Add it to your transformIgnorePatterns in your Jest config:
module.exports = {
transformIgnorePatterns: ['node_modules/(?!(uuid))'],
}
Edit: After a bit more testing, it turns out that anything I import into the test is "not a function".
I had very similar symptoms once: builds and works as excepted, yet ...is not function in jest. The culprit was a circular dependency I accidentally introduced with my story. Maybe check for that.
As I suspected, the issue was in the naming. Renaming the files and directory to just wrapper solved the issue.

How to mock fetch call inside of child´s componentDidMount with Jest/Enzyme [duplicate]

I would like to test a small React web app where I use the global fetch method.
I tried to mock fetch in this way:
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
... but the mock seems to be ignored, while the built-in fetch seems to be used: Error: connect ECONNREFUSED 127.0.0.1:80 ... looks like a failed call to the built-in fetch.
I then tried to use jest.fn instead of jest.spyOn:
global.fetch = jest.fn(endpoint =>
Promise.resolve({
json: () => Promise.resolve(mockResponse)
})
);
... and was surprised to see a different error. Now the mock seems to be taken into consideration, but at the same time is not working correctly:
TypeError: Cannot read property 'then' of undefined
8 | this.updateTypes = this.props.updateTypes;
9 | this.updateTimeline = this.props.updateTimeline;
> 10 | fetch('/timeline/tags')
| ^
11 | .then(res => res.json())
12 | .then(tags => tags.map(tag => <option value={tag} key={tag} />))
13 | .then(options => options.sort((a, b) => a.key.localeCompare(b.key)))
I find the documentation of Jest and React Testing Library a bit confusing, honestly. What might be the problem with what I am doing?
Edit
The React component I am trying to test is called "App", was generated with Create React App, and was changed to include a call to fetch. I can gladly provide the code for this component, but I believe that the problem lies in the tests.
At the beginning of my App.test.js file, I import React from 'react';, then import { render, fireEvent, waitFor, screen } from '#testing-library/react';, and finally import App from './App';. I subsequently attempt to mock fetch in one of the ways I described, and then declare the following test:
test('renders a list of items, upon request', async () => {
const app = render(<App />);
fireEvent.click(screen.getByText('Update'));
await waitFor(() => screen.getByRole('list'));
expect(screen.getByRole('list')).toBeInTheDocument();
expect(screen.getByRole('list')).toHaveClass('Timeline');
});
Finally, I end my test file with global.fetch.mockRestore();.
That there's ECONNREFUSED error instead of fetch is not defined means that fetch has been polyfilled. It's not a part of JSDOM and isn't polyfilled by Jest itself but is specific to current setup. In this case the polyfill is provided by create-react-app.
It's always preferable to mock existing global function with jest.spyOn and not by assigning them as global properties, this allows Jest to do a cleanup. A thing like global.fetch = jest.spyOn(global, 'fetch') should never be done because this prevents fetch from being restored. This can explain TypeError: Cannot read property 'then' of undefined error for seemingly correctly mocked function.
A correct and safe way to mock globals is to mock them before each test and restore after each test:
beforeEach(() => {
jest.spyOn(global, 'fetch').mockResolvedValue({
json: jest.fn().mockResolvedValue(mockResponse)
})
});
afterEach(() => {
jest.restoreAllMocks();
});
There should be no other modifications to global.fetch in order for a mock to work correctly.
A preferable way to restore mocks and spies is to use configuration option instead of jest.restoreAllMocks because not doing this may result in accidental test cross-contamination which is never desirable.
Another reason for TypeError: Cannot read property 'then' of undefined error to appear is that Jest incorrectly points at fetch line, and the error actually refers to another line. This can happen if source maps don't work correctly. If fetch is mocked correctly and there are other then in the same component, it's a plausible explanation for the error.

How do you write object literal line coverage in Typescript Mocha unit-test?

Lead:
New to working with typescript and writing unit tests using Mocha and Chai.
Question
Any tips on how I can go about getting 100% line coverage in unit tests with an object literal that isn’t in a class? Trying to avoid going static if at all possible, but unit testing still has to hit 100% to pass.
// constants.ts
export default {
path: “./example”,
name: “Example Name”
}
// constants.spec.ts
// How do I unit test ‘export default’ for 100% line coverage?
// I have tried
import chai from "chai";
import * as constants from “./constants.ts”;
describe(“constants”, () => {
it(“Constants literals should have a length of 2“, () => {
chai.expect(constants.default.length).equal(2);
});
});
// The mocha test succeeds, but the line still says it hasn’t been tested.
I think I found the answer, but I am sure there is an easier way to use and test literals in Typescript.
describe("Constants", async () => {
it("can be created", async () => {
const obj = constants.default;
chai.should().exist(obj);
});
});
Typescript Mocha Chai unit-test 100% line coverage

Timeout when attempting to connect to mongo from jest unit tests

I want to write some unit tests with jest and mongoose to validate data interaction with mongo.
I don't want to mock mongoose here because I specifically want to validate the way that mongo documents are created/modified/handled.
package.json is configured to leave node modules unmocked:
{
"jest": {
"unmockedModulePathPatterns": [
"node_modules"
]
}
}
In my actual test, I have set up a beforeAll() hook to take care of connecting to mongo:
const mongoose = require('mongoose');
describe('MyTest', () => {
beforeAll((done) => {
mongoose.connect('mongodb://127.0.0.1:27017/test');
let db = mongoose.connection;
db.on('error', (err) => {
done.fail(err);
});
db.once('open', () => {
done();
});
});
it('has some property', () => {
// should pass but actually never gets run
expect(1).toBe(1);
});
});
Here's the output:
/usr/local/bin/node node_modules/jest-cli/bin/jest.js --verbose
Using Jest CLI v0.10.0, jasmine2
FAIL src/lib/controllers/my-controller/__tests__/my-test.js (5.403s)
MyTest
✕ it has some property
MyTest › it has some property
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at Timer.listOnTimeout (timers.js:92:15)
1 test failed, 0 tests passed (1 total in 1 test suite, run time 5.903s)
Process finished with exit code 1
The test times out every time because done() is never called in the beforeAll() hook - no errors thrown nor anything printed to console. I can place breakpoints in the beforeAll() hook to validate the code is being run. It appears that mongoose is hanging whilst attempting to open a connection to Mongo, and then the jest tests are timing out.
When I'm running similar code outside of the jest environment, it connects as expected (nigh on instantly). Suspecting that it could be causing problems, I've experimented with disabling jest's automock feature completely, but the behaviour remains unchanged.
I imagine I've missed something incredibly obvious... any ideas what could be going on?
jest-cli v. 0.10.0
mongoose v. 4.4.11
Updates:
Tried replacing ES6 arrow function syntax with plain function(done) {}. No difference.
Tried making the test async by passing done parameter, and calling it on test completion. No difference.
Tried calling mongoose.connect() after the declaration of error and connected event handlers
Tried commenting out all mongoose-related code to check that the beforeAll() hook is working correctly - it is.
Jest-jasmine is different from Jasmine.
The syntax you used actually belongs to Jasmine 2.0+, not Jest-jasmine. So if you want to continue to use jest, you have to look into jest docs to find the answer.
Even more, "beforeAll" is not a standard jest injected variables, see jest api.
I got your code run with Jasmine 2.3.4, it runs just fine. I tried Promise/pit in jest to finish this job but failed.
First, install jasmine.
npm install -g jasmine
mkdir jasmine-test
cd jasmine-test
jasmine init
jasmine examples
touch spec/mongodbspec.js
Here is my directory structure:
fenqideMacBook-Pro:jasmine-test fenqi$ ls -R
.:
spec/
./spec:
mongodbspec.js support/
./spec/support:
jasmine.json
Then, edit spec/mongodbspec.js, I just add one line " 'use strict'; " to your code.
'use strict';
const mongoose = require('mongoose');
describe('MyTest', () => {
beforeAll((done) => {
mongoose.connect('mongodb://127.0.0.1:27017/test');
let db = mongoose.connection;
db.on('error', (err) => {
done.fail(err);
});
db.once('open', () => {
done();
});
});
it('has some property', () => {
// should pass but actually never gets run
expect(1).toBe(1);
});
});
Last, run 'jasmine' :
fenqideMacBook-Pro:jasmine-test fenqi$ jasmine
Started
.
1 spec, 0 failures
Finished in 0.023 seconds

Resources