Error trying to unit test Mongoose schema validation with Jest - node.js

I'm new to Jest and try to set up a simple test script:
"use strict"
// Local dependencies
const userModel = require('./user.model');
// Setting controllers
describe("Users endpoint", () => {
describe("Validating user schema", () => {
it("Should return an error if name property is missing", () => {
const user = new userModel();
user.validate((error) => {
expect(error.errors.name.kind).toBe("required");
});
});
});
});
When running Jest, I got the following error:
SyntaxError: Identifier 'global' has already been declared
2 |
3 | // Local dependencies
> 4 | const userModel = require('./user.model');
I search on Google and didn't find anything related to the 'global' identifier.
Any help would be really appreciate.
Thanks,
Steve

Ok so after digging a bit more, I figured out that the issue was with a const global inside my require script:
const global = require(path.join(__dirname, '..', 'config', 'config'));
If I change the "global" name for anything else (i.e. globalTest), it will works.
Sousing "global" seems to be not allowed.

Related

How to resolve the issue "Waiting for update signal from WDS..."?

export default function SinglePost() {
const location =useLocation();
const paths=location.pathname.split("/")[2];
console.log(paths);
useEffect(()=>{
const getpost= async () => {
const res=axios.get("/posts/"+paths)
console.log(res);
}
},[paths])
What should I do?
I checked out the some solution
The first solution says to change the webpack.config.js file and I am not able find that file. And is this the correct solutions.

How correctly require in Jest file ? (with a module pattern js file)

Probably a stupid question
I start using JEST for testing.
I have my js app :
var app={ init:function{ //some code}, ... }
module.exports = app;
And my app.test.js :
const {app} = require('../js/index.js')
test('type of variable', () => {
expect(typeof app.someFunction(app.someVar)).toBe("'number");
});
And I have the classic error :
TypeError: Cannot read property 'someFunction' of undefined
It seem very stupid, but I never understand clearly these require on client side...
It work perfectly with the Jest getStarted example
My arbo is
-js
----index.js
-tests
----app.text.js
module.exports = app
The above line returns object {}, and you are trying to pick app from object in your destructing line var {app}
Remove {}
const app = require('../js/index.js')
test('type of variable', () => {
expect(typeof app.someFunction(app.someVar)).toBe("'number");
});

Node JS Error: Cannot find module './services'

I am trying to create stubs using sinon to run the test but its throwing error.
Its trying to find a module services and saying the module is not found but I have the services.js in the same folder as test. So I am not sure why its failing.
Can someone please advise what is wrong in the code.
1) the car-lookup controller "before each" hook for "should return filtered TAP response":
Error: Cannot find module './services' from 'C:\nodejsworkspace\olive\server\api\car-lookup'
at Function.module.exports [as sync] (node_modules\proxyquire\node_modules\resolve\lib\sync.js:40:15)
at Proxyquire._resolveModule (node_modules\proxyquire\lib\proxyquire.js:137:20)
at Proxyquire.<anonymous> (node_modules\proxyquire\lib\proxyquire.js:205:35)
at Array.reduce (<anonymous>)
at Proxyquire._withoutCache (node_modules\proxyquire\lib\proxyquire.js:204:6)
at Proxyquire.load (node_modules\proxyquire\lib\proxyquire.js:129:15)
at Context.<anonymous> (test\unit\server\api\car-lookup\car-lookup.controller.test.js:30:18)
controller = proxyquire('../../../../../server/api/car-lookup/car-lookup.controller.js', {
'./services': { taClient: new MockTaClient() }
});
});
Below is how I think the services are being exported from the car-lookup.controller.js
Below is car lookup controller.js
If you see in the first line it is trying to import services and services is not a direct js file. I have an index.js file in the ../../directory which is what the first line is referring to. Directory structure is also below. Please advise.
>server
> api
> car-lookup
>car-lookup.controller.js
>server
>services
>index.js
'use strict';
const services = require('../../services');
const { ApiError, ValidationError } = require('../../errors');
const AccountModel = require('../../models/account-model');
const lookupAccount = (req, res, next) => {
const retrieveAccount = (oktaToken) => {
return services.tapClient.retrieveAccount(req.body);
};
const sendResponse = (account) => {
res.send(new AccountModel(account));
};
const onError = (err) => {
next(err instanceof ValidationError ?
new ApiError(err, 400) :
err);
};
retrive()
.then(retrieveAccount)
.then(sendResponse)
.catch(onError);
};
module.exports = {
lookupAccount
};
Make sure you are exporting the file services properly

nodejs/mocha/chai as promise : variables used in expected async function initialized outside

I am brand new to mocha/chai and I spent 2 days trying to solve the following issue without any success (please note that the code below is just to present the concept, it is not the real one).
I have got a JS file called "api.js" in which some variables such as SERVER_URL are initialized at the top of the file through dotenv framework.
api.js :
const SERVER_URL = process.env.SERVER_URL;
async function startAPI () {
return new Promise ( (resolve, reject) => {
console.log(`${SERVER_URL}`);
resolve();
});
exports = {startAPI};
Now I have got "test.js" file in which :
test.js:
require('../api');
it('the test', async () => {
return await expect(api.startAPI()).to.be.fulfilled;
});
The problem is that SERVER_URL is undefined during the test and I cannot modify the api.js (as I am not the owner), just the test.js.
How can I run the test with the SERVER_URL variable set correctly (to process.env.SERVER_URL value from api.js) ?
Is there a solution without any refactoring ?
And if not what is the best solution ?
Experts, thanks in advance for your precious help
A way to improve testability is to use process.env.SERVER_URL instead of SERVER_URL where possible - or getServerUrl():
const getServerUrl = () => process.env.SERVER_URL;
This way process.env.SERVER_URL can be mocked at any point.
An alternative is to import module after process.env.SERVER_URL was mocked. This should involve decaching if there's more than one test that uses this module, because it won't be re-evaluated otherwise.
const decache = require('decache');
...
let originalServerUrl;
beforeEach(() => {
originalServerUrl = process.env.SERVER_URL;
});
beforeEach(() => {
process.env.SERVER_URL = originalServerUrl;
});
it('the test', async () => {
decache('../api');
process.env.SERVER_URL = '...';
const api = require('../api');
await expect(api.startAPI()).to.be.fulfilled;
});
If it's expected that there's no SERVER_URL in tests, it can be just discarded after it was mocked:
The easiest way would be just to set these variables when you run your test from CLI:
e.g. in npm scripts:
"scripts": {
"test": "SERVER_URL='http://example.com' mocha"
}
or directly from terminal:
$ SERVER_URL='http://example.com' npm test
But better solution would be mock environment variables in your tests with little refactoring. And need proxyquire to be installed. And actually async/await is not needed here.
const proxyquire = require('proxyquire').noPreserveCache() // noPreserveCache is important to always have refreshed script with new process.env.SERVER_URL in each test
const MOCKED_SERVER_URL = 'http://example.com'
describe('example', () => {
let initialServerUrl
let api
beforeEach(() => {
initialServerUrl= process.env
})
afterEach(() => {
process.env = initialServerUrl
})
it('fulfilled', () => {
process.env.USE_OTHER_CODE_PATH = MOCKED_SERVER_URL
api = proxyquire('../api', {})
return expect(api.startAPI()).to.be.fulfilled
})
it('rejected', () => {
process.env.USE_OTHER_CODE_PATH = ''
api = proxyquire('../api', {})
return expect(api.startAPI()).to.be.rejected
})
})
You can set .env variables with mocha using the following line:
env SERVER_URL=htt://api.yourserver.com/ mocha test
This way mocha knows what to expect from your process.env.SERVER_URL

How to mock module function using proxyquire

I need to mock 'mkdirp-promise' node module which exposes a constructor function as below
mkdirpPromise(dirPath)
.then(() => {
console.log('ABCDEFGH');
resolve(dirPath);
})
.catch((error) => {
console.log('HeABCDEFGHre');
const details = error.message;
const err = customError.failed_create_downloads_directory()
.withDetails(details);
reject(err);
});
Im able to mock it using proxiquire as below for the first time:-
let mkdirpPromiseMock = sinon.stub().rejects();
const sthreeDownloadMock =
proxyquire('./../../modules/sThreeDownload', {
joi: joiMock,
fs: fsMock,
'#monotype/core-error': {
errors: {
ApiError: customErrorMock,
},
},
'aws-sdk': awsSDK,
'mkdirp-promise': mkdirpPromiseMock,
path: pathMock,
});
Now i want to override mkdirpPromiseMock in 2nd test case with
mkdirpPromiseMock = sinon.stub().resolves();
which im not able to. Any help is appreciated.
Proxyquire is not compatible with jest.
You need to use a mocking library like rewiremock.
Please have a look at this answer which goes into detail.
REPL example

Resources