Can't access function after name changed in node.js - javascript

There is a function in one of my files in project which I changed it's name and can't access it with new name! still the old name is available to call
I tried deleting node_modules and install it again using npm i
there is the code to both files I'm using:
soapCall.js
before:
function call(username, password){
...
}
module.exports = call
after:
function checkUser(username, password){
...
}
module.exports = checkUser
how I imported and used:
app.js
const soap = require('../../models/soapCall');
...
soap.checkUser(username, password);
it's weired that still I can't access the new function name
I was using name call before that and STILL can use call function in my app.js file

call is already available as a method on the function prototype - Function.prototype.call. This means soap is a function, which is why call works, but checkUser doesn't.
soap is a function because you're exporting a function from your file, and simply renaming it in your main file. If you want to change the name, either change the import name:
const checkUser = require("../../models/soapCall");
Or export an object and use it as such:
module.exports = { checkUser };
// Main file
const soap = require("../../models/soapCall");
soap.checkUser(...);
The object method will also allow you to export multiple functions from the one file - you can get these into their own variables with destructuring:
module.exports = { checkUser, otherFunc };
// Main file
const { checkUser, otherFunc } = require("../../models/soapCall");
checkUser(...); // Calls checkUser function
otherFunc(...); // Calls otherFunc function

You are exporting a function not an Object, so you need to directly call soap().
And about being able to run call, it's part of function prototype. So you got confused with Function.prototype.call()

Use it like this, as per the comment by #Wiktor Zychla
soapCall.js
exports.checkUser(username, password){
}
app.js
const soap = require('../../models/soapCall');
soap.checkUser(username, password);

Related

passing a function through res.render() in express.js and accessing that from a pug file

i am new in express.js. i used pug for templating. I need to pass a function through res.render() and that will accessible from pug file. Is it possible? If possible then how? please help me.
app.js
passingMethod= (info) => {
console.log(info);
}
app.get('/',(req, res)=>{
res.render('first.pug', {methods: {passingMethod: this.passingMethod}})
});
and first.pug
script.
var onBtnClick= (event) => {
var methods = !{JSON.stringify(methods)}
console.log(methods)
//want to accessing passingMethod function from here
}
.fb-area
.fb
This is good?
button#good(onclick='onBtnClick(event)') Good
button#bad Bad
Depends on the type of function you are passing. Provided your function returns a value, this will be easy. Assign your function as an object to a variable and pass the variable to the res.render() method like this:
//Within your Route or Route-controller
var someVariable = someFunction()
res.render('templateName', {someVariable})
Then Call your variable in pug template

How to define a Javascript class static method by using a function defined elsewhere?

I have a Javascript class (env: node.js v12 or above) defined like this:
module.exports = class MyClass extends SomeOtherClass {
// ...
static async someMethod() {
const result = await this.exampleSuperMethod()
return result
}
// ...
}
I'm extending SomeOtherClass, which defines a static method called exampleSuperMethod, which is used in my someMethod as described above.
Now, I'd like to define the someMethod method by using a function defined somewhere else. This is needed because the function is something generic and I'd like not to repeat the same code in my classes. More over, defining the function in an external module, I can test it once only and reuse everywhere my shared and tested code.
To achieve this, I'd like to have a function defined like the following:
const myMethod = (MainClass) => async () => {
const result = await MainClass.exampleSuperMethod({
// do something
})
return result
}
module.exports = myMethod
In this function, I'm allowing the dependency injection of MainClass (needed to reach the exampleSuperMethod), by exporting a high order function which defines my needed function with a closure.
With a class defined like this, I'll be able to mock simply the "main" SomeOtherClass and pass in to the high order function this mock, which exposes the exampleSuperMethod. In the real usage, my idea is to inject the this element and get back the function ready to be plugged in my class as a static method. But I'm not sure how to achieve this last point.
My main class could become something like the following:
const useMyMethod = require('./path-to-file/my-method.js')
module.exports = class MyClass extends SomeOtherClass {
// ...
// how to replace the following to use the
// function received by the call to
// useMyMethod(this) ?
//
static async someMethod() {
const result = await this.exampleSuperMethod()
return result
}
// ...
}
I'm wondering how to replace the initial definition of someMethod with the function returned by useMyMethod(this).
Thank you for your help!

Using Jest spyOn a module that is initiated

Within an ExpresS API I'm using the Postmark library to send an email, which is initiated like this:
var postmark = require("postmark");
var client = new postmark.Client("aaaa-bbbbb-cccc");
And then used to send a password reset mail later on with:
client.sendEmailWithTemplate(
// Options here
);
Now, I would like to test this function has been called, but I have difficulties finding out how to mock/spy on this.
I have tried the following (simplified):
const request = require("supertest");
const app = require("../server/app");
const postmark = require("postmark");
jest.mock("postmark");
describe("API Tests", () => {
test("it should give a reset link when requesting with existing e-mail address", () => {
return request(app)
.post("/api/auth/passwordreset")
.send({
email: "user1#test.test"
})
.then(response => {
expect(postmark.Client).toHaveBeenCalled();
});
});
});
This works, but it's only testing if postmark has been used, since I can't figure out how to actually test the client.sendEmailWithTemplate method
Any suggestions on how to accomplish this?
EDIT: following up on #samanime answer I created a repo to illustrate the 'challenge'
https://github.com/Hyra/jest_test_example
You can specifically mock out the Client function that is returned by the mocked postmark to return an object with mocked functions.
In Jest, you can provide specific mocking code for a node_modules by creating a folder named __mocks__ at the same level as node_modules, i.e.,
/project-root
/node_modules
/__mocks__
Note, that is two underscores on each side.
In there, make a function named <package_name>.js (in your case, postmark.js). It will then load whatever is exported by that when you use the mock.
In that file, you can mock it out as needed. Something like this would probably work:
// global jest
module.exports = {
Client: jest.fn(() => ({
sendEmailWithTemplate: jest.fn(() => {})
}))
};
It doesn't have to be as compact as this, but basically it makes postmark have a function called Client which returns an object that has a functiono called sendEmailWithTemplate, both of which are mocks/spys.
Then you can just check if postmark.Client.sendEmailWithTemplate was called.
The one gotcha is you'll need to be sure to reset all of these in between tests. You could do this manually in your beforeEach(), but if you are going to reuse it, I like to add an extra function named __reset() which will reset the code and just call that:
// global jest
const mockedPostmark = {
Client: jest.fn(() => ({
sendEmailWithTemplate: jest.fn(() => {})
}))
};
mockedPostmark.__reset = () => {
mockedPostmark.Client.mockClear();
mockedPostmark.Client.sendEmailWithTemplate.mockClear();
};
module.exports = mockedPostmark;
You can add additional functions as needed as well.

Node.js: create module with separation of actions

I have a node application and I took the following functionality and put it in separate file in new folder as a new module. In this file I need to handle some action like save delete edit etc. I have two questions:
Should I separate the functionality inside this file to actions and
expose it differently?
In any case how should I call to this functionality with the
parameters which is needed to all the actions like req, res, path?
I'm looking for concrete examples.
This is the code that I use:
module.exports = function () {
const fs = require('fs')
function fileAction (req, res, urlAction) {
switch (urlAction) {
case 'save':
const writeStream = fs.createWriteStream('c://myfile.txt', { flags: 'w' })
req.pipe(writeStream)
req.on('end', function () {
console.log('Finish to update data file')
})
res.end()
break
case 'delete':
case 'update':
default:
}
}
I like this approach more than implementing functions inside and export lexical scope.
Simply with this approach I feel like the concern of "exporting" is separated from the implementation of the functions. In addition to that you can rename the functions you are going to export. Most importantly you might control better what you want and do not want to export.
var delete= function(){
};
var update = function(){
};
var save = function(){
};
module.exports.update = update;
module.exports.delete = delete;
module.exports.save = save;
Then you'll be able to call methods from your main file:
var file = require('./file.js');
file.save();
file.delete();
file.update();
You should do something more object-oriented:
module.exports = {
save: function () {
},
delete: function () {
},
update: function () {
}
}
Then you'll be able to call methods from your main file:
const FileLib = require('./fileLib.js')
FileLib.save()
If you plan to use this as logic inside an Express application, you do not really need to use req and res directly from inside your module except if you are writing an Express middleware or a router.
But what I would recommend you is to use your library from the router:
const FileLib = require('./fileLib.js')
router.put('/file/:id', function (req, res) {
// Do your stuff with your library
FileLib.save(req.param('fileToSave'))
res.send()
})
Your library should not be too coupled to the express architecture unless it's a middleware.
Writing RESTful Express routing might also be a good idea. Use HTTP verbs to specify your action to the API.

In a Node app with express JS, how can I include and run a separate JS file?

I have a javascript file that contains some functions that grab an RSS feed and save the contents in a database. I originally had it being called by the HTML page, but I want this file to instead be running in the back-end all the time (grabbing updates from the RSS feed and saving it to a database).
My question is, how can I attach and run this separate javascript within my app? I assume it will look like this:
In app.js:
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.SomeFunction();
This isn't working though. Also, would variables declared in my app.js be available in RSSReader.js?
Thanks.
how can I attach and run this separate javascript within my app?
The app.js code you show should work just fine. The key is that you have to make your RSSReader.js file into a module that exports the functions it wants to be public:
So, inside of RSSReader.js, you would have something like this:
module.exports = {
someFunction: function() {
// code here
},
someOtherFunction: function() {
// code here
}
};
Then, in your other file, you can load that module and use it like you had:
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.someFunction();
RssReader.someOtherFunction();
node.js documentation for modules is here.
Also, would variables declared in my app.js be available in
RSSReader.js?
No, they would not unless you explicitly declared the app.js variables as properties on the global object. The usual node.js convention for sharing from app.js to another module is that you create an initializer method for the RSSReader.js module (you can call it init) and you pass it any context it needs (usually an object with some properties on it) from app.js and the RSSReader.js module can then store that context for its use.
So, if you want to share some variables from app.js to RSSReader.js, you could share them via a .init() method like this:
RSSReader.js
var data;
module.exports = {
init: function(options) {
data = options;
},
someFunction: function() {
// code here can access the data variable
},
someOtherFunction: function() {
// code here can access the data variable
}
};
app.js
var RSSReader = require('./public/javascripts/RSSReader.js');
RSSReader.init({express: express, db: db});
RSSReader.someFunction();
RssReader.someOtherFunction();

Categories