Need help in passing this simple mocha test in javascript - node.js

Here, I wrote a simple utilities class in Javascript that parses and stringify Json data.
//public/js/utilities.js
function UtilitiesClass(){
var parserJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.parse(obj);
};
}
var stringifyJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.stringify(obj);
};
}
}
module.exports = UtilitiesClass
Then in my test.js
require('../public/js/utilities.js');
describe('JS Utilities Classs Tests', function () {
var jsonObjToStr, strtojsonObj;
beforeEach(function () {
this.jsonObjToStr = [1, 2, 3, 4];
this.strtojsonObj = "[1, 2, 3, 4]";
});
it('should parse a string into JSON ', function () {
expect(parserJson(this.strtojsonObj)).to.not.be.undefined;
});
it('should stringify JSON into a string', function () {
expect(stringifyJson(this.jsonObjToStr)).to.not.be.undefined;
});
});
Then when I tried running mocha, I got the following error output.
andy#LINUXAWCM:~/Projects/Javascript/e-shop-gadgets$ mocha
JS Utilities Classs Tests
1) should parse a string into JSON
2) should stringify JSON into a string
0 passing (12ms)
2 failing
1) JS Utilities Classs Tests should parse a string into JSON :
ReferenceError: parserJson is not defined
at Context.<anonymous> (test/test.js:12:18)
2) JS Utilities Classs Tests should stringify JSON into a string:
ReferenceError: stringifyJson is not defined
at Context.<anonymous> (test/test.js:16:16)
Why wouldn't this simply work? The require statement on public/js/utilities.js comes out fine. But it's saying the parserJson and stringifyJson are not defined or found when really it's already loaded.
Isn't it?

Simply declaring a variable inside a function is not enough, you need to return these since they aren't available outside the function's scope.
You're also exporting a function and not calling it.
Also requiring a file doesn't magically make your variables available to your scope.
//public/js/utilities.js
function UtilitiesClass(){
var parserJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.parse(obj);
};
}
var stringifyJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.stringify(obj);
};
}
return {
parserJson: parserJson,
stringifyJson: stringifyJson
};
}
module.exports = UtilitiesClass;
var util = require('../public/js/utilities.js')();
util.parserJson(...) //etc
Though you probably don't need to export a function, just each method.
//public/js/utilities.js
var parserJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.parse(obj);
};
}
var stringifyJson = function(obj){
if (typeof(obj) !== "undefined") {
return JSON.stringify(obj);
};
}
module.exports = {
parserJson: parserJson,
stringifyJson: stringifyJson
};
Then you'd use
var utils = require('../public/js/utilities.js');

Related

How to load JS file in another JS file in Node

Cannot load JS file in my app (getting undefined) and I want to emulate the same effect as the tag in the plain HTML.
I have tried
import Api from './api' -> tells me that none of the defined function is a function (don't have any circular dependencies), so my best guess it that Api was not initalized or something?
Tried module.exports on Api -> tells me that Api is undefined
Tried exports.Api -> tells me that the function which i try to call from the Api is not a function
I tried to require and a few more things, which I cannot even recall, and none of it seems to be working. Main issue is that I don't recognize the format of the JS file in question since I never seen a variable declared as a function that contains other functions, so explanation on that might come in handy tbh.
var Api = (function() {
var requestPayload;
var responsePayload;
var messageEndpoint = '/api/message';
var sessionEndpoint = '/api/session';
var sessionId = null;
// Publicly accessible methods defined
return {
sendRequest: sendRequest,
getSessionId: getSessionId,
// The request/response getters/setters are defined here to prevent internal methods
// from calling the methods without any of the callbacks that are added elsewhere.
getRequestPayload: function() {
return requestPayload;
},
setRequestPayload: function(newPayloadStr) {
requestPayload = JSON.parse(newPayloadStr);
},
getResponsePayload: function() {
return responsePayload;
},
setResponsePayload: function(newPayloadStr) {
responsePayload = JSON.parse(newPayloadStr);
},
setErrorPayload: function() {
}
};
function getSessionId(callback) {
var http = new XMLHttpRequest();
http.open('GET', sessionEndpoint, true);
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function () {
if (http.readyState === XMLHttpRequest.DONE) {
var res = JSON.parse(http.responseText);
sessionId = res.session_id;
callback();
}
};
http.send();
}
// Send a message request to the server
function sendRequest(text, context) {
// Build request payload
var payloadToWatson = {
session_id: sessionId
};
payloadToWatson.input = {
message_type: 'text',
text: text,
};
if (context) {
payloadToWatson.context = context;
}
// Built http request
var http = new XMLHttpRequest();
http.open('POST', messageEndpoint, true);
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function() {
if (http.readyState === XMLHttpRequest.DONE && http.status === 200 && http.responseText) {
Api.setResponsePayload(http.responseText);
} else if (http.readyState === XMLHttpRequest.DONE && http.status !== 200) {
Api.setErrorPayload({
'output': {
'generic': [
{
'response_type': 'text',
'text': 'Something went wrong.'
}
],
}
});
}
};
var params = JSON.stringify(payloadToWatson);
// Stored in variable (publicly visible through Api.getRequestPayload)
// to be used throughout the application
if (Object.getOwnPropertyNames(payloadToWatson).length !== 0) {
Api.setRequestPayload(params);
}
http.send(params);
}
}());
Code above is provided by IBM (for the Watson Assistant I am trying to work with) and the code is for the Node.JS application which works fine.
It works fine since the code above is simply included in the app through the tag in their index.html and voila, it works, but I don't have that ability (read below).
My issue is that their app is also a client app and I want to transfer all of that 'back-end' stuff to my REST API and that is why I am trying to use the code above.
var Api = (function() {
var messageEndpoint = "/api/message";
// Publicly accessible methods defined
return {
messageEndpoint: messageEndpoint
};
})();
module.exports = Api ;
And you can use it like
const api = require("./api");
console.log(api);
So basically just add module.exports = Api ; in api file and you would be able to use it.

NodeJS RESTful API - How to handle 'undefined' request variables properly?

I am developing a RESTful API using NodeJS and Express.
I noticed that incoming requests sometimes lack of some expected variables, which cause the program to crash, saying it couldn't set the value of a variable, to an 'undefined' value - as no value arrived with the request.
Example:
The application is expecting variableY, but instead variableX is being sent:
formData: { variableX: 'valueX' }
The program is expecting to receive variableY, with the following code:
const checkVariables = Joi.validate({
variableY: req.body.variableY,
}, schema);
The application crashes with the following error:
TypeError: Cannot read property 'variableY' of undefined
I thought about a few ways to handle that, including declaration of variables upon application initiation and using them along, using try-catch.
Another way will be to use if-else, if-chaining, or case-switch, but as you understood of course I am looking for the cleanest way to achieve that.
Any ideas?
Thank you.
** EDIT **
Progressed and managed to achieve the result using the object only. Once trying to reach any of it's inner fields the error will be thrown anyway, example:
if(req.body.variableY == undefined){console.log('The expected variable is undefined');} //true
When the validation addresses a field inside the 'undefined' object:
if(req.body.variableY.dataId == undefined){console.log('The expected variable is undefined');} //crashes
The following error is being thrown again:
TypeError: Cannot read property 'variableX' of undefined
After doing some more digging around, found this Stackoverflow thread:
How to check if object property exists with a variable holding the property name?
Tried using hasOwnProperty, but the same kind of error is being thrown:
TypeError: Cannot read property 'hasOwnProperty' of undefined
Tried wrapping variable declaration using try-catch, still didn't work:
try{
var variableX = req.body.variableX
var variableXDataId = req.body.variableX.dataId
}
catch(e){
res.status(400).send('Wrong request error: Please check your request variables and try again');
}
As this is a really basic validation that should be addressed by most of the RESTful APIs (validating that you get the expected incoming variables inside the request, so the program won't crash by having errors it can't handle - what is the common solution for such problems (expected / unexpected request validation)?
Thank you.
You can take another approach, check req.body before you reach checkVariables:
let body = req.body;
// data - your req.body
// requiredKeys - is an array of strings , [ key1, key2 ... keyN] | string[]
const setKeys = ( data, requiredKeys )=>{
if( !typeof requiredKeys.length ){
requiredKeys = [];
}
if(requiredKeys.length) requiredKeys.forEach( k =>{
k = k.replace(/\+/g,'/');
let keysList = [];
if( /\/+/g.test(k)){
keysList = k.split('/');
}else{
keysList = [k];
}
let [firstKey, ...rest] = keysList;
if( typeof data[firstKey] === 'undefined' ){
data[firstKey] = {};
}
if( rest.length ){
data[firstKey] = setKeys(data[firstKey], [rest.join('/')] );
}
})
return data;
}
let checkedData= setKeys(body, ['variableT','variableP/noname/emptyObj','custom/object/does/not/exist/but/it/will/be/created/here']);
const checkVariables = Joi.validate(checkedData, schema);
UPDATE
Below you will find an working example on how things should work during a /(let's say /usersStatus/:id ) request:
const express = require('express')
const app = express()
const port = 3000
const setKeys = (data, requiredKeys) => {
if (!typeof requiredKeys.length) {
requiredKeys = [];
}
if (requiredKeys.length) requiredKeys.forEach(k => {
k = k.replace(/\+/g, '/');
let keysList = [];
if (/\/+/g.test(k)) {
keysList = k.split('/');
} else {
keysList = [k];
}
let [firstKey, ...rest] = keysList;
if (typeof data[firstKey] === 'undefined') {
data[firstKey] = {};
}
if (rest.length) {
data[firstKey] = setKeys(data[firstKey], [rest.join('/')]);
}
})
return data;
}
/**
* Mock some data
*/
const getUserData = (req, res, next) => {
if (typeof req.body === 'undefined') {
req.body = {};
}
req.body = {
variableY: {
someName: 23
},
variableZ: {
name: 3,
type: {
id: 5,
typeName: 'something',
tags: ['a', 'b', 'c']
}
}
};
console.log('Middleware 1 getUserData');
next();
}
/**
* 1. Setup our middleware for checking keys
* "requiredKeys" is an array of strings
*/
const middlewareSetKeys = (requiredKeys, wrappedMiddleware) => {
return (req, res, next) => {
console.log('Middleware 2 middlewareSetKeys');
if (typeof req.body === "undefined") {
console.log('Leaving Middleware 2 since we don\'t have req.body');
next();
}
/**
* Update "req.body" with keys that we want to have available
* in our next middleware
*/
req.body = setKeys(req.body, requiredKeys);
if (typeof wrappedMiddleware === 'function') {
return wrappedMiddleware.call(this, req, res, next);
} else {
next();
}
}
}
/**
* 2. Let's assume a "user status" situation
* 2.1. We need userInfo from database
* 2.2. Some info won't be retrieved, unless the user accesed some parts of the website to trigger some mechanisms that allows those fields to be exposed, therefore the lack of keys
* 2.3. But we know those keys/objects, and we still want to be present so our code won't crash.
*/
// lets call our getUserData
app.get(
'/', // this path is for some userInfo
getUserData, // this returns userInfo and appends it to `req.data`
middlewareSetKeys([
'userActivity/daily/jobs', // these won't exist in getUserData because the user is lazy and he didn't apply for any JOBS
'userStatus/active/two-weeks-ago', // these won't exist in getUserData because the user joined two days ago. BUT WE STILL NEED IT coz reazons.
]), // We set our desired-later-to-use keys
(req, res, next) => {
/**
* 3. Now our req.body will have our keys
* even if they didn't exist in the getUserData middleware
*/
console.log('Middleware 3 Your middleware');
console.log(req.body);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(req.body, null, 2))
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
you can use express validator https://www.npmjs.com/package/express-validator
to validate incoming request.Then add this to your controller where a,b,c ,d are parameters you want to valaidate
const nonEmptyFields = ['a', 'b', 'c', 'd'];
nonEmptyFields.forEach(field => req.assert(field, `${field} cannot be blank`).notEmpty());
const errors = req.validationErrors();
if (errors) {
return res.status(400).send(errors);
}
for validating a field inside a field you can try doing this
typeof(req.body && req.body.name !== undefined)
A solution will be to set a default empty object to replace undefined at a parent level:
// checking for body.variableX.variableZ with object destructuring ES6
const {body = {}} = request;
const {variableX = {}, variableY} = body;
const {variableZ} = variableX.variableZ;
// or prior ES6
var body = request.body || {};
var variableX = body.variableX || {};
var variableY = variableX.variableY;
// or in a statement
var variableY = request.body && request.body.variableX ? request.body.variableX.variableY : undefined;
Based on that you can create your own function like getValue(request, 'body.variableX.variableY') to return null if any parent or the end value is undefined:
// asumes the value in the path is either object or undefined
function getValue(rootObj, path = '') {
const parts = key.split('.');
let value = rootObj || {};
let part;
while ((part = parts.shift()) && value !== null) {
value = value[part] || null;
}
return value;
};

How to stub a nodejs "required" constructor using sinon?

I'm writing unit tests for a method that uses the email-templates module like this:
var EmailTemplate = require('email-templates').EmailTemplate;
module.exports = {
sendTemplateEmail: function (emailName, data, subject, to, from) {
var template = new EmailTemplate(__dirname + "/../emails/" + emailName);
data.from = FROM;
data.host = config.host;
return template.render(data)
.then(function (result) {
return mailer.sendEmail(subject, to, from, result.html, result.text);
})
.then(function () {
log.info(util.format("Sent %s email to %s. data=%s", emailName, to, JSON.stringify(data)));
return Promise.resolve();
})
.catch(function (err) {
return Promise.reject(new InternalError(err, "Error sending %s email to %s. data=%s", emailName, to, JSON.stringify(data)));
});
}
};
The unit test looks like this:
var assert = require("assert"),
sinon = require("sinon"),
Promise = require("bluebird"),
proxyquire = require("proxyquire");
describe('mailer#sendTemplateEmail', function () {
var templates,
template;
beforeEach(function() {
templates = {
EmailTemplate: function(path) {}
};
template = {
render: function(data) {}
};
sinon.stub(templates, "EmailTemplate").returns(template);
});
it("should reject immediately if template.render fails", function () {
const TO = {email: "user1#example.com", first: "User"};
const FROM = {email: "user2#example.com", first: "User"};
const EMAIL_NAME = "results";
const SUBJECT = "Results are in!";
const DATA = {
week: 10,
season: "2015"
};
var err = new Error("error");
var mailer = proxyquire("../src/mailer", {
"email-templates": templates
});
sinon.stub(template, "render").returns(Promise.reject(err));
return mailer.sendTemplateEmail(EMAIL_NAME, DATA, SUBJECT, TO, FROM)
.then(function () {
assert.fail("Expected a rejected promise.");
})
.catch(function (err) {
assert(err.message === "error");
assert(mailer.sendEmail.notCalled);
});
});
};
The problem I'm encountering is on the first line of the sendTemplateEmail function which instantiates a new EmailTemplate object. The EmailTemplate constructor being called points to the non-stub EmailTemplate function defined in the beforeEach, rather than the sinon stub created on the last line of the beforeEach. If I evaluate the require('email-templates').EmailTemplate statement, however, it correctly points to the sinon stub. I'd prefer not to have to change my code to call the require statement inline like:
var template = new require('email-templates').EmailTemplate(__dirname + "/../emails/" + emailName);
Is there any way to accomplish the stub the way I'm intending?
You can inject your dependency when you construct your mailer - exp:
function mailer(options) {
options = options || {};
this.email_template = options.email_template;
}
Then in the sendTemplateEmail function - use the email_template member.
Also - not sure about your mailer code - but if you need your mailer to act as a singleton in your code (and it isn't already) - you can add this to your mailer:
module.exports = {
getInstance: function(emailTemplate) {
if(this.instance === null){
this.instance = new mailer(emailTemplate);
}
return this.instance;
}
}
Then when you require your mailer you can use the syntax:
var template = new require('email-templates').EmailTemplate(__dirname + "/../emails/" + emailName);
var mail = mailer.getInstance(template);
This way your application (unit test framework or your actual/real-world application) will determine the type of mailer that will be used for the lifetime of the process.

Wrapping NodeJS's net.createServer into a producer of customised sockets

I'm trying to make a function which behaves like net.createServer, except that it returns objects which are wrappers around sockets, instead of sockets.
(The point of these will be to do automatic data conversion.)
My latest attempt looks like:
var net = require('net');
var util = require('util');
var stream = require('stream');
var EventEmitter = process.EventEmitter;
exports.createServer = createServer;
function createServer(arg0, arg1) {
var server;
var netServer;
var ocb;
if (typeof arg1 === 'function') {
// options, callback
netServer = net.createServer(arg0, callback);
ocb = arg1;
} else if (typeof arg0 === 'function') {
// callback
netServer = net.createServer(callback);
ocb = arg0;
} else {
// options?
netServer = net.createServer(arg0);
ocb = null;
}
server = new Server(netServer);
function callback(socket) {
ocb(new LiftedSocket(socket));
};
return server;
;
}
function Server(netServer) {
this.netServer = netServer;
}
util.inherits(Server, EventEmitter);
Server.prototype.listen = function() {
this.netServer.listen.apply(this.netServer, arguments);
}
function LiftedSocket(socket) {
stream.Duplex(this);
this.socket = socket;
}
util.inherits(LiftedSocket, stream.Duplex);
LiftedSocket.prototype._read = function(size) {
console.log('_read', size);
// transforming code goes here
this.socket.read(size);
}
LiftedSocket.prototype._write = function(chunk, encoding, callback) {
console.log('_write', chunk, encoding, callback);
// transforming code goes here
this.socket.write(chunk, callback);
}
But when tested (by trying to pipe from a returned LiftedSocket) it fails with errors including:
Uncaught TypeError: Cannot read property 'pipesCount' of undefined
at LiftedSocket.Readable.pipe (_stream_readable.js:453:16)
Uncaught TypeError: Cannot read property 'flowing' of undefined
at LiftedSocket.Readable.on (_stream_readable.js:691:44)
I expect I'm doing something wrong when constructing the LiftedSocket, but I can't think what.
I had called the superclass constructor incorrectly. It should have been:
stream.Duplex.call(this, {})

How to spy on a property that is not exported

I have a module "sitescollection" like this:
var site = require('./site'); // <- this should be stubbed
var sitesCollection = function(spec) {
var that = {};
that.sites = {};
that.findOrCreateById = function(id) {
if (typeof(that.sites[id]) == "undefined") {
that.sites[id] = site({id: id}); // <- its used here
}
return that.sites[id];
};
return that;
};
module.exports = sitesCollection;
so within sitescollection, site is a module that is not exported. But inside the code, i use it. Now i'm writing jasmine specs for #findOrCreateById().
I want to spec my the findOrCreateBy() function. But i want to stub the site() function, because the spec should be independent from the implementation. Where do i have to create the spyed method on?
var sitescollection = require('../../lib/sitescollection');
describe("#findOrCreateById", function() {
it("should return the site", function() {
var sites = sitescollection();
mysite = { id: "bla" };
// Here i want to stub the site() method inside the sitescollection module.
// spyOn(???,"site").andRetur(mysite);
expect(sites.findOrCreateById(mysite.id)).toEqual(mysite);
});
});
You can achieve this using https: //github.com/thlorenz/proxyquire
var proxyquire = require('proxyquire');
describe("#findOrCreateById", function() {
it("should return the site", function() {
// the path '../../lib/sitescollection' is relative to this test file
var sitesCollection = proxyquire('../../lib/sitescollection', {
// the path './site' is relative to sitescollection, it basically
// should be an exact match for the path passed to require in the
// file you want to test
'./site': function() {
console.log('fake version of "./site" is called');
}
});
// now call your sitesCollection, which is using your fake './site'
var sites = sitesCollection();
var mysite = {
id: "bla"
};
expect(sites.findOrCreateById(mysite.id)).toEqual(mysite);
});
});

Resources