I am using nodejs and webdriver for automation tests. I am trying to export a function from one js file to another. e.g there is a function called abc under file abc.js and i want to use that function with other file called xyz.js. I tried using export and require but it exports and runs entire test (abc.js) instead of just a function.
//abc.js
console.log('print this');
client= function client() {
driver.get(baseUrl + '/#/login');
};
exports.client = client;
//xyz.js
var client1 = require('abc.js').client();
Requiring a module for the first time causes the module to be cached and it's code to be executed, that's why you're seeing your "print this" log. Next time you call your client function you shouldn't see it.
This is not relevant to the question, but still, in your xyz.js file, since your function isn't returning anything you can use:
require('abc.js').client();
Instead of:
var client1 = require('abc.js').client();
In your abc.js, there's no need for a named function, you can just use:
var client = function() {
...
};
give it a try
function abc(){
console.log('print this');
this.client= function client() {
driver.get(baseUrl + '/#/login');
};
return this;
}
module.exports = abc;
//xyz.js
var abc = require('abc.js')();
abc.client();
its a good practice when capsulating objects in nodejs
Related
I'm trying to learn Node.js and I have a pretty good app now, but I wanted to implement a library (venom-bot) to send some text messages. My problem is that I'm having trouble trying to use functions outside the primary file. Here is my code:
// Dependencies
const server = require("./lib/server")
const venom = require("venom-bot")
// Declare the app
const app = {}
// Init function
app.init = () => {
// Start the server
server.init()
}
// Init venom-bot
venom.create().then((client) => start(client))
// A function to test if I can send the message
async function testing(msg) {
await msg.sendText(...some code here...)
}
function start(client) {
app.msg = client
// Here, if I pass app.msg as an argument, works
// My problem is that I can't use app.msg outside of here,
// even with the module.exports down there
// (I'm trying to use it on a helpers.js file).
testing(app.msg)
// Execute the application
app.init()
}
// Export the app
module.exports = app
On the helpers.js file I'm requiring it this way:
// Dependencies
const app = require("./index.js")
// A function to test
async function sendMsg(msg) {
await msg.sendText(...some code here...)
}
helpers.send = () => {
sendMsg(app.msg)
}
module.exports = helpers
Whenever helpers.send gets invoked, it should correctly use the async function right above the helpers.send passing the app.msg as argument, at least I think it should. What I'm missing here?
The error I got is:
(node:18148) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'sendText' of undefined
On testing purpose, I'm trying to simple call that helper when I receive a get request to a specified route.
I am working with PhantomJS and have a file named file1.js which has the following code:
var fs = require('fs');
system = require('system');
var inputfile=system.args[1];
var stream = fs.open(inputfile,'r');
var data = stream.read();
var config = JSON.parse(data);
var user_input=config.input;
var output_format=config.output;
stream.close();
The above code reads a JSON file and takes the user_input and output_format that were stored in the JSON file.
I have another file as well that is named as file2.js and now I want to call file2.js here from inside file1.js and want to pass both user_input and output_format as arguments.
The code of file2.js doesn't need to be added here.
The important thing is that file1.js should call file2.js and pass these two arguments to it. file2.js will then perform the required operations on those arguments.
I tried injectJS but it doesn't work since it only works with pages e.g. page.injectJS.
Also, injectJS only accepts one parameter which is a filename and nothing else. Thus, I am unable to achieve what I wanna achieve.
Please help me. Thanks in advance.
Just try this flow. may be it will help you
var page = require("webpage").create()
page.open(url, function () {
page.includeJs(file1.js, function () {
page.evaluate(function (params1, params2) {
page.includeJs(file2.js, function () {
page.evaluate(function (params3, params4) {
console.log(params3, param4)//this will print 10,20
}, params1, params2)
})
}, 10, 20)
})
})
I have stubbed the content of file, so I can run through only outer function
file.html
<body onload ="test('file.txt')">
<body>
file.js
const fs1 = require('fs');
let param;
module.export = {
test,
test1,
param
}
function test (outputParam) {
let fileData = test1(outputParam);
param = fileData;
}
function test1(outputParam) {
let data = fs1.readFileSync(outputParam);
return data;
}
Here as you see I load function test from html onload and in turn test1 calls and reads file, I have stubbed this file content as shown in the test below
When I run the test I want to see the variable param has the file content value
test.spec.js
let sinon = require("sinon");
let filejs = require('./file.js');
it('should run only the outer function' ,function() {
// I try to stub my function here
sinon.stub(filejs,'test1').callsFake ((someArg) => {
return "this is my file content";
});
// Now I will call my test function
filejs.test(someArg);
})
As you seen above I have stubbed function test1, still when I run the test I see test1 gets called and it reads the real file.
I am using mocha , I am new to stub or mock concepts, any suggestion is really appreciated.
You should probably try to stub readFileSync.
const fs = require('fs');
// ...
sinon.stub(fs, "readFileSync").callsFake ((someArg) => {
return "this is my file content";
});
Besides that, I can spot two issues with your code.
The real readFileSync will return a Buffer if called without a second parameter, not a string like your stub does.
The body onload event only exists inside the DOM. The fs module is only available in Node.js. If you run your code in a browser, you won't be able to use fs.readFileSync. If you run it in Node, your HTML file and the onload event won't be useful.
I'm currently trying to build an array of functions. I have a folder full of modules where each module has a function run and the following line
exports.run = run;
var run = function(db){
// Run some code
}
I then have a file I call in node which does the following:
require("fs").readdirSync("./channels").forEach(function(file) {
var func = require("./channels/" + file);
channels.push(func);
console.log("Adding " + file);
console.log(channels);
});
The function above successfully adds in each file with type undefined. I'm unable to run the functions because of this. How can I successfully build this array of functions?
The reason your code doesn't work as you expect it to, is variable hoisting in JavaScript.
var run = function(db){
// Run some code
}
exports.run = run;
If you don't want to push your exports line to the bottom of your function, then you'll have to declare run as a stand-alone function, rather than assigning it to a variable.
exports.run = run;
function run(db){
// Run some code
}
I am currently a beginner on RequireJS and i am a bit in trouble with the AMD concept, especially the way that RequireJS is defining it.
My aim is to build a smart Loader that call the specific Parser he needs.
To summarize my needs :
(A) I create my loader : new Loader(source)
(B) source represents the data to load. That's a simple string.
(C) A Loader object is created. It executes some algorithm to decide what is the best Parser to use. Eventually, it downloads the parser from a remote location. Finally, it loads the parser dynamically.
My problem is this one : How can I load a module/plugin without expliciting it in the define? I cant set it in the define([theParserHere]) because I am unable to know which Parser is needed.
The require function sounds like it could be used for your purposes. It allows for loading of modules, but not defining a new module.
Your loader could call a function such as the following to load a module dynamically when needed:
function loadParser(name, fn) {
require(["parsers/" + name], fn);
}
name would be the name of the parser or a path or something (note that my path was just an example) and fn is a callback to call when the loading has been completed. The first argument to the function would be the loaded module.
This function could be placed in your loader object or just sit inside the define:
define(function () {
function Loader(text) {
this.text = text;
this.parser = null;
this.loadParser();
}
Loader.prototype.loadParser = function () {
var self = this;
var parserName = this.getParserName();
require(["parsers/" + parserName], function (Parser) {
self.parser = Parser;
self.parse();
});
}
Loader.prototype.getParserName = function () {
//mystery logic to determine language...
return "some-parser-name";
}
Loader.prototype.parse = function () {
if (!this.parser) {
throw "No parser loaded";
}
//do your parsing logic...
}
return Loader;
});
Now, if I were actually doing this, I would use Q or jquery deferreds or something for resolving the parser inside the require callback function instead of all that function calling.