So basically I want this block:
const {someFunction} = require("/somePath");
exports.exportedFunction = (req, res) => { someFunction() }
to work like this block:
exports.exportedFunction = (req, res) => {
const {someFunction} = require("/somePath");
someFunction();
}
But without repeating the imports. How to prevent repeating imports into every single export? I want to have one import from which I can use the function into every export without importing exactly into exports. Is that even possible?
UPDATE: okay, there's small update. I have made a minimum requirement problem recreation and it looks like this:
//index.js
const express = require("express");
const app = express();
const router = require("./router");
exports.exportableStuff = () => {
return [1,2,3];
};
app.use("/", router);
app.listen(3000, () => {
console.log("i am listening");
});
//router.js
const express = require("express");
const router = express.Router();
const controller = require("./controller");
router.get("/", controller.testModule);
module.exports = router;
//controller.js
const {exportableStuff} = require("./index");
exports.testModule = (req, res) => {
console.log("it has been done");
exportableStuff();
res.send("<h1>hello, user</h1>");
}
UPDATE2: I actually managed to fix the closures myself. What I actually did to make this work is changing this:
const {exportableStuff} = require("./index");
Into:
const model = require("./index");
And call the function in my controller with model.exportableStuff().
Problem oficially solved, but if you have better idea, I'm all ears.
According to your comment, I think you might want to do following thing?
// index.js
module.exports = { someFunction }
// router.js
// case1
const { someFunction } = require("./index.js")
someFunction() // it will work
// case2
const index = require("./index.js")
index.someFunction() // it will work
But, if you want to export your someFunction to another exports
then use new function, you need to do like this.
// another.js
const { someFunction } = require("./index.js")
exports.exportedFunction = someFunction
// router.js
const { exportedFunction } = require("./another.js")
exportedFunction() // it will work
Related
I need to change a route params at runtime in nodejs.
In my code I set a route using:
const troutes = require('./src/routes/testroutes')(page,sessionId)
app.use('/teste' + sessionId, troutes)
But, in runtime, sometimes the "page" object param is recreated and it becomes invalid. But the "sessionId" param is the same, no changes.
Then I create a new "page" and need remake the route, because the old route has a invalid page.
if I use:
let page={newpage};
const troutes = require('./src/routes/testroutes')(page,sessionId);
My urls don´t work because the route use the old invalid "page" param object.
How could I delete or change the old route and use the new route with the new "page" object?
//server.js
const express = require('express')
const app = express()
const server = require('http').Server(app)
const port = 3001
const host = 'http://localhost'
const callbackUrl = `${host}:${port}`;
let page={page};
let sessionId='sessionId';
const troutes = require('./src/routes/testroutes')(page,sessionId)
app.use('/teste' + sessionId, troutes)
....
});
//routes.js
const express = require('express');
const router = express.Router();
module.exports = function (page,sessionId) {
router.get('/'+sessionId+'/getMyNumber', async (req, res) => {
const cc = await page.evaluate(() => {
return getMyNumber();
});
console.log(cc);
res.send({ "data": cc });
});
return router;
}
since you called require('./src/routes/testroutes')(page,sessionId) method only once in file, it loads only once. so passed parameters/initializations within function executed only once.
the router which is initialized and returned is used for further request processing.So new request will only trigger method of router.
if you want page to be dynamic, it would work if you move page inside router, instead of passing it from wrapper function as below.
const express = require('express');
const router = express.Router();
module.exports = function (sessionId) {
router.get('/'+sessionId+'/getMyNumber', async (req, res) => {
let page = {newPage}
const cc = await page.evaluate(() => {
return getMyNumber();
});
console.log(cc);
res.send({ "data": cc });
});
return router;
}
in the following code i'm using expresjs
//index.js
app.use('/',routes());
//app/routes.js
module.exports = function() {
express = require('express');
const loggedUserProfileController = require('../controllers/LoggedUserProfile');
const userProfileController = require('../controllers/userProfile');
const router = express.Router();
router.post('/get-logged-user-profile', loggedUserProfileController.getLoggedUserProfile());
router.post('/get-user-profile-data', userProfileController .getUserProfile());
return router;
}
controllers
//controllers/loggedUserProfile.js
module.exports =
{
getLoggedUserProfile:function(){
return getLoggedUserProfile:function= (req, res, next) => {
getUserCustomData();
}
}
getUserCustomData(){console.log('logged user')}
//controllers/userProfile.js
module.exports =
{
getUserProfile:function(){
return getUserProfile:function= (req, res, next) => {
getUserCustomData();
}
}
getUserCustomData(){console.log('user')}
the output is 'user'
the second getUserCustomData overrides the first one how is that possible regarding that i didn't import it in module.exports
Yes this is possible. A function definition is hoisted, declared, and assigned. If you define another in the same scope after the previous one, the new definition will now overwrite the original.
Identifiers used in function statements/definitions are not constants and are therefore subject to re-assignment. If you want it to remain static after creation you can do const getUserCustomData = function () { ... } instead and the second attempt to re-assign will throw an error for you.
I want to check a case that certain routes are calling the correct controller use Jest specific (mock or spy).
It is case specific for unit testing. Somebody can help me how to check it use jest. I don't need verify kind of
expect (status code or res object) i need to check if controller have been called.
Thanks!
For instance:
// todoController.js
function todoController (req, res) {
res.send('Hello i am todo controller')
}
// index.spec.js
const express = require('express');
const request = require('request-promise');
const todoController = require('./todoController');
jest.mock('./todoController');
const app = express();
app.get('/todo', todoController)
test('If certain routes are calling the correct controller , controller should to have been called times one.', async() => {
await request({url: 'http://127.0.0.1/todo'})
expect(todoController).toHaveBeenCalledTimes(1);
})
Actually if you search, there are many references out there.
In the following, I share a few ways that I know.
One of the big conceptual leaps to testing Express applications with mocked request/response is understanding how to mock a chained
API eg. res.status(200).json({ foo: 'bar' }).
First you can make some kind of interceptor, this is achieved by returning the res instance from each of its methods:
// util/interceptor.js
module.exports = {
mockRequest: () => {
const req = {}
req.body = jest.fn().mockReturnValue(req)
req.params = jest.fn().mockReturnValue(req)
return req
},
mockResponse: () => {
const res = {}
res.send = jest.fn().mockReturnValue(res)
res.status = jest.fn().mockReturnValue(res)
res.json = jest.fn().mockReturnValue(res)
return res
},
// mockNext: () => jest.fn()
}
The Express user-land API is based around middleware. AN middleware that takes a request (usually called req), a response (usually called res ) and a next (call next middleware) as parameters.
And then you have controller like this :
// todoController.js
function todoController (req, res) {
if (!req.params.id) {
return res.status(404).json({ message: 'Not Found' });
}
res.send('Hello i am todo controller')
}
They are consumed by being “mounted” on an Express application (app) instance (in app.js):
// app.js
const express = require('express');
const app = express();
const todoController = require('./todoController');
app.get('/todo', todoController);
Using the mockRequest and mockResponse we’ve defined before, then we’ll asume that res.send() is called with the right payload ({ data }).
So on your test file :
// todo.spec.js
const { mockRequest, mockResponse } = require('util/interceptor')
const controller = require('todoController.js')
describe("Check method \'todoController\' ", () => {
test('should 200 and return correct value', async () => {
let req = mockRequest();
req.params.id = 1;
const res = mockResponse();
await controller.todoController(req, res);
expect(res.send).toHaveBeenCalledTimes(1)
expect(res.send.mock.calls.length).toBe(1);
expect(res.send).toHaveBeenCalledWith('Hello i am todo controller');
});
test('should 404 and return correct value', async () => {
let req = mockRequest();
req.params.id = null;
const res = mockResponse();
await controller.todoController(req, res);
expect(res.status).toHaveBeenCalledWith(404);
expect(res.json).toHaveBeenCalledWith({ message: 'Not Found' });
});
});
This is only 1 approach to testing Express handlers and middleware. The alternative is to fire up the Express server.
Imagine this code:
var authenticate = (req, res, next) => {
...
};
Can I export the above code like these?
module.exports = {authenticate}; or module.exports = authenticate;
Can I import above code like these?
var {authenticate} = require('./middleware/authenticate'); or var authenticate = require('./middleware/authenticate');
This should solve all your troubles: https://flaviocopes.com/commonjs/
exporting value:
autheticate.js
module.exports = authenticate;
other-file.js
const authenticate = require('./autheticate.js')
or exporting object
autheticate.js
module.exports = {authenticate};
other-file.js
const {authenticate} = require('./autheticate.js')
I am building an Express app. I currently have an error in the following file, factoryRepository.js
let appReference = null;
module.exports.init = (app) => {
appReference = app;
};
module.exports.getRepositoryFactory = () => {
let repositoryFactory = {
getUserRepository: () => {
return require("./UserRepository").init(appReference.get('models').User);
}
};
return repositoryFactory;
};
appReference.get throws a TypeError because appReference is still null even after I have called module.exports.init somewhere else.
I have tried to make a function that returns appReference so I can see in what state it is. I have been able to get app rather than null, it is only in the context of getUserRepository that it stays null.
The faulty line is only called when I ping a certain route.
EDIT:
This is app.js, the context from which module.exports.init is being called
import express from 'express';
import passport from 'passport';
import config from './config/config';
let app = express();
// Setup models
app.set('models', require('./app/models'));
require('./app/repo/repositoryFactory').init(app);
// Setup config
require('./config/init')(app);
// Setup routes
require('./app/routes')(app, passport);
// Setup passport
require('./app/auth')(passport, config);
// Route to ends
require('./config/endpoints')(app);
export default app;
public.js is the logic given to my router, and it is here where I call the faulty code with repositoryFactory.getUserRepository()
let repositoryFactory = require('../repo/RepositoryFactory').getRepositoryFactory();
module.exports.doLogin = (req, res) => {
let success = () => {
res.redirect('/');
};
let error = (message) => {
res.status(500).json(message);
};
let userRepository = repositoryFactory.getUserRepository();
userRepository.findOrCreate({
facebookId: req.user.id,
displayName: req.user.displayName
}, success, error);
};
module.exports.doLogout = (req, res) => {
req.logout();
res.json({
success: true,
message: 'You\'ve succesfully logged out.'
});
};
This looks like a scope issue. Let's say we simplify your three files as follows, and also put them all in the same directory (for simplicity here):
app.js:
'use strict';
const express = require('express');
let app = express();
require('./repositoryFactory').init(app);
const myPublic = require('./public');
repositoryFactory.js:
'use strict';
let appReference = null;
module.exports.init = (app) => {
appReference = app;
};
module.exports.getRepositoryFactory = () => {
return appReference ? 'I have an app reference!' : 'No app reference!';
};
public.js:
'use strict';
let repositoryFactory = require('./RepositoryFactory').getRepositoryFactory();
console.log(repositoryFactory);
This is going to log No app reference! because the repositoryFactory is not a singleton. The repositoryFactory instance in app.js is a different instance than the repositoryFactory instance in public.js.
One solution would be to pass a parameter for the repositoryFactory instance. repositoryFactory.js would be unchanged, but app.js might look like this:
'use strict';
const express = require('express');
let app = express();
const repositoryFactory = require('./repositoryFactory')
repositoryFactory.init(app);
const myPublic = require('./public');
myPublic.init(repositoryFactory);
myPublic.log();
And the corresponding public.js might look like this:
'use strict';
let repositoryFactory = null;
module.exports.init = (myRepositoryFactory) => {
repositoryFactory = myRepositoryFactory.getRepositoryFactory();
}
module.exports.log = () => {
console.log(repositoryFactory);
}