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
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.
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");
});
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
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
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