After stubbing function still it calls the real function - javascript

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.

Related

Testing a file that calls its own function

I have a file that is the entry-point to my application;
const main = async () => {
// Do stuff
}
main().then();
I understand that I can export the main function, delete the call in the first file and in a separate file import and call the function there;
const entry = require('./rewritten-entry.js');
entry.main().then();
But for arguments sake lets say I really want to test this first file's main function. As soon as I import the file in my test, the main function will execute before I even reach the test code;
const entry = require('./original-entry.js') // <-- main function executes here
const test = {
// Do test stuff
}
For a test, I don't want this to happen. Likewise I don't want to mock the function since it is exactly what I want to test.
I see this common 'init' logic all over the place so I imagine there is a way to test this.

PhantomJS - How to call file2.js from file1.js (by passing arguments from file1 to file2)

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)
})
})

Expect fs.watch callback to be called in Jasmine

I have a class that accepts a callback in it's constructor. It also has a method loadFile that gets the content from the file, modifies it a bit and calls the callback with the modified content. Up to this point a class can be easily tested.
Now, I want to add a watch feature. loadFile will do what I just described and will start watching a file. Every time the file changes, the process will be repeated (load the file -> modify the content -> call the callback). I try to test it using Jasmine but I cannot make it work.
The simplified code looks like this:
const path = require('path')
const watch = require('fs').watch
const write = require('fs').writeFile
class Loader {
constructor (callback) {
this.callback = callback
}
loadFile (file) {
watch(file, (p, e) => {
console.log('path changed', p, e)
// do some important stuff here
this.callback(p)
})
}
}
describe ('Loader', () => {
var loader
var callback
beforeEach(() => {
callback = jasmine.createSpy('callback')
loader = new Loader(callback)
})
it('converts a markdown file', () => {
// this file already exists
const file = path.join(__dirname, 'md', 'header.md')
loader.loadFile(file)
write(file, 'hello', 'utf8')
expect(callback).toHaveBeenCalled()
console.log('end of test')
})
})
The command line result is:
Started
end of test
path changed change header.md
path changed change header.md
F
Failures:
1) Loader converts a markdown file
Message:
Expected spy callback to have been called.
Stack:
Error: Expected spy callback to have been called.
at Object.it (/path/to/spec/callback.spec.js:34:22)
1 spec, 1 failure
Finished in 0.015 seconds
This test does not load actual content, I simplified it to show the problem I encountered: the callback is called, but after the expectation.
I've spent a lot of time figuring out what is wrong but I failed. I think I've tried every possible combinations of using done() that Jasmine provides, but I didn't have any luck. I would appreciate any help with this.

exporting a function in node.js

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

Issues with exports

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
}

Categories