unit testing with mocha not finding function - node.js

So I'm trying to unit test a function I wrote here is the function:
function compareServices(service1, service2) {
if (service1.name != service2.name) {
return false
}
if (service1.port != service2.port) {
return false
}
if (service1.target != service2.target) {
return false
}
if (service1.address != service2.address) {
return false
}
return true
}
it is located inside my main.js file. Now When I try to run the test I get an error saying:
Main #compareServices() should compare if two services match:
TypeError: main.compareServices is not a function
at Context.<anonymous> (test/stelaSpec.js:21:25
And here is my test file:
var expect = require("chai").expect;
var main = require("../src/main.js");
describe("Main", function(){
describe('#compareServices()', function() {
it('should compare if two services match', function() {
var svc1 = {
"name": "test.fg.service",
"port": 8001,
"target": "mac-book",
"address": "192.2.2.2"
}
var svc2 = {
"name": "test.fg.service",
"port": 8001,
"target": "mac-book",
"address": "192.2.2.2"
}
var result = main.compareServices(svc1, svc2);
expect(result).equal(true)
});
});
});
Why is it saying it is not a function when it is?

Make sure to have the following at the end of your main.js file:
module.exports = {
compareServices: compareServices
};
This will make the function accessible to other javascript files that require it.

You change your code for main.js as below:
function compareServices(service1, service2) {
if (service1.name != service2.name) {
return false
}
if (service1.port != service2.port) {
return false
}
if (service1.target != service2.target) {
return false
}
if (service1.address != service2.address) {
return false
}
return true
}
to
// if you use case => In test file you need to declare var main = new Main();
// with Main = require(... + '/main.js');
var Main = function(){};
Main.prototype.compareServices = function(service1, service2) {
if (service1.name != service2.name) {
return false
}
if (service1.port != service2.port) {
return false
}
if (service1.target != service2.target) {
return false
}
if (service1.address != service2.address) {
return false
}
return true
}
module.exports = Main;
Or
var Main = function(){};
Main.compareServices = function(service1, service2) {
if (service1.name != service2.name) {
return false
}
if (service1.port != service2.port) {
return false
}
if (service1.target != service2.target) {
return false
}
if (service1.address != service2.address) {
return false
}
return true
}

Related

I need help to get a simple query for MongoDB (SQL equivalent: "select speed from values")

I need help to get a simple query for MongoDB (SQL equivalent: "select speed from values"). But I can't find a solution for that.
Node.js backend for Vue.js
// a Part of Init-function:
await collection.replaceOne({}, {
speed: {
value: 65,
type: 2,
},
eightSpeed: {
value: 0.0043,
type: 2,
},
oSpeed: {
value: 0.31,
type: 2,
},
minusSpeed: {
value: 2.42,
type: 2,
}
}
//...
Now I need the query like this: http://192.168.220.220:3000/settings/getValue/speed to get an object speed.
const express = require("express");
const mongodb = require("mongodb");
const SettingsRouter = new express.Router();
SettingsRouter.get("/getValue/:value", async function (req, res) {
try {
const val = req.params.value; // req.body.text;
const select = {};
select[`${val}.value`] = 1;
console.log("settings.js:", "/getValue/:name", select);
const collection = await loadMongoCollection();
const value = await collection.findOne({},select)//.toArray();
res.status(201).send(value);
} catch (error) {
res.status(500).send("Failed to connect Database");
console.error("settings.js:", "/getValue/:name:", error);
}
});
async function loadMongoCollection() {
const dbUri = process.env.MONGODB_CONNSTRING || config.dbUri;
const MongoDB = process.env.MONGODB_DB || config.db;
try {
const client = await mongodb.MongoClient.connect(dbUri, {
useNewUrlParser: true,
});
const conn = client.db(MongoDB).collection("values");
return conn;
} catch (error) {
console.error("settings.js:", "loadMongoCollection:", error);
}
}
When I try it, I get all (not only the Speed Object) what I expected, or nothing.
What I do wrong?
EDIT 2022.01.06:
I try it to change my database:
data = {
speed: {
value: 65,
type: 2,
},//...
}
//...
await collection.replaceOne({}, {values:data}, { upsert: true });
And then the query:
const select = {[`values.${val}.value`]:"1"};
const where = {}; //{"values":val};
const value = await collection.find(where,select,).toArray();
But it will not work in rest... is there an issue in mongo package?
When I do it in https://cloud.mongodb.com - it works:
But my request returns all values...
Log shows:"'settings.js:', '/getValue/:name', { 'values.speed.value': '1' }"
In the screenshot you show the projection is values.speed.value, but in your endpoint you have:
const select = {};
select[`${val}.value`] = 1;
Which would evaluate to speed.value. To mimic what you have on the MongoDB console this should be:
const select = {};
select[`values.${val}.value`] = 1;
So, I changed my Frondend (vue) to spred all Values. I maked some Helper Functions:
CheckForChangedObj
check two object for changes
updateObj
copy all data from object into another
export function CheckForChangedObj(targetObject, obj) {
if (targetObject === typeof undefined || targetObject == {}) {
return true
}
if (JSON.stringify(targetObject) !== JSON.stringify(obj)) {
return true
}
return false
}
export function updateObj(targetObject, obj) {
let keys = Object.keys(obj)
for (let k in keys) {
try {
let key = keys[k]
if (!targetObject.hasOwnProperty(key)) {
//define target, if not exist
targetObject[key] = {}
}
//Workaround for References
if (obj[key].hasOwnProperty("__v_isRef")) {
if (targetObject[key].hasOwnProperty("__v_isRef")) {
targetObject[key].value = obj[key].value
} else {
targetObject[key] = obj[key].value
}
} else {
//Source i a Norm Value
//check for an Object inside, then go in...
if ("object" === typeof obj[key] && !Array.isArray(obj[key])) {
updateObj(targetObject[key], obj[key]) // recurse
} else {
//not else-if!!! __v_isRef: true
if (targetObject[key].hasOwnProperty("__v_isRef")) {
targetObject[key].value = obj[key]
} else {
targetObject[key] = obj[key]
}
}
}
} catch (error) {
console.log(
"key:",
keys[k],
"Error:",
error
)
}
}
}
Then spreading...
import {updateObj,CheckForChangedObj } from "../tools/tools"
beforeMount() {
this.getAllValuesAPI()
setInterval(() => {
this.checkForChanges()
// ml("TABLE", this.values)
}, 10000)
},
setup() {
let prevValues = {}
let values = {
speed: {
id:1,
type: SettingType.Slider,
value: ref(0)
}
//...
}
function checkForChanges() {
//intervaled function to get changes from API
let changed = CheckForChangedObj(this.values, this.prevValues)
if (changed) {
updateObj(this.prevValues, this.values)
setValuesToAPI()
}
else{
getAllValuesFromAPI()
}
}
async function getAllValuesFromAPI() {
//get ALL Settings-Data from API, and put them in values
const res = await axios.get(`settings/getAll`)
return updateObj(this.values, res.data[0].values) u
}
}
When you have a better solution, please help...

TypeError: dbConn.GetInstance is not a function

I trying to create a common database connection class using typescript for my nodejs express application that returns the MongoDB database object as follows but I always get TypeError: dbConn.GetInstance is not a function
const config = require("config");
const MongoClient = require('mongodb').MongoClient;
export class dbConn {
private db = null;
static url = config.database.uri;
static options = {
bufferMaxEntries: 0,
reconnectTries: 5000,
useNewUrlParser: true,
useUnifiedTopology: true,
};
private constructor() { }
private static instance: dbConn;
public static GetInstance() {//I also tried removing static keyword but still the error remains
if (dbConn.instance == null)
{
dbConn.instance = new dbConn();
}
return dbConn.instance;
}
public getDb() {
if (dbConn.instance.db) {
return dbConn.instance.db;
}
MongoClient.connect(dbConn.url, dbConn.options, function(err: any, db: any){
if(err) {
console.log(err);
return null;
}
dbConn.instance.db = db.db(config.database.name);
return dbConn.instance.db;
});
}
}
Updated 01-Aug-2020
I invoke the above instance from app.ts and my controllers as follows:
app.ts file
const dbConn = require('./utils/db/dbConn');
...//code removed for clarity
const app = express();
const server = http.createServer(app);
...//code removed for clarity
server.listen(port, ()=> {
dbConn.GetInstance().getDb();//I get the error here
console.log('Server running')
});
module.exports = app;
my controller file
getAll = async (pageNumber:any, pageSize:any) : Promise<PageResult<Team>> => {
return new Promise<PageResult<Team>>(async function (resolve, reject){
let result = new PageResult<Team>(pageSize, pageNumber);
var dbo = dbConn.GetInstance().getDb();//same error here too.
var query = {};
var recCount = await dbo.collection("teams").find().count();
if (recCount == 0) {
result.IsSuccessful = true;
result.ReasonForFailure = process.env.NO_RECORDS || "No record(s) to show.";
return resolve(result);
}
if (pageSize == -1) { //-1 means to return all records
dbo.collection("teams")
.find(query)
.sort({ name: 1 })
.toArray(function(err: any, resultSet: any) {
if (err) {
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
return reject(result);
} else {
result.IsSuccessful = true;
result.TotalRecords = recCount;
result.PageNumber = parseInt(pageNumber);
result.PageSize = parseInt(pageSize);
result.Data = resultSet;
return resolve(result);
}
});
} else {
dbo.collection("teams")
.find(query)
.sort({ name: 1 })
.skip((parseInt(pageNumber)-1)*parseInt(pageSize))
.limit(parseInt(pageSize)).toArray(function(err: any, resultSet: any) {
if (err) {
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
return reject(result);
} else {
result.IsSuccessful = true;
result.TotalRecords = recCount;
result.PageNumber = parseInt(pageNumber);
result.PageSize = parseInt(pageSize);
result.Data = resultSet;
return resolve(result);
}
});
}
});
}
Can you please assist what is wrong or what is the missing piece to get this to work?
Thanks,
Hemant.
It seems you're using commonjs as module-resolution strategy. Your import will be the problem in that case. Try changing it to:
const dbConn = require('./utils/db/dbConn').dbConn;
or
const { dbConn } = require('./utils/db/dbConn');
or
import {dbConn } from './utils/db/dbConn';
Here's a simple example to show what's going on. Consider this simple ts-class:
export class TestClass {
static test():void {
console.log("it works")
}
}
It will be transpiled into:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestClass = void 0;
class TestClass {
static test() {
console.log("in workds");
}
}
exports.TestClass = TestClass;
//# sourceMappingURL=index.js.map
If you then require this with const TestClassModule = require('./test-class');, TestClassModule will yield:
{ TestClass: [Function: TestClass] }
Hence, you need to use const { TestClass } = require('./test-class');.

Nodejs cloud functions - Not all code paths return a value

I am writing a cloud function to create a node in firebase realtime database. The code seems to be returning a value for all paths. Where is it that i am going wrong? Is there a scenario where gamesRef.push() is not called and is that the reason the error is being thrown?
Cloud Function:
export const createGame = functions.https.onCall((data, context) => {
const game_type = data.game_type;
if (game_type != GAME_PRACTISE || game_type != GAME_MULTIPLAYER || game_type != GAME_FRIENDS) {
return {
"status": 403,
"id": null
};
} else {
const uid = data.uid;
const status = GAME_STATUS_OPEN;
var players = [uid];
let max_players;
if (game_type == GAME_PRACTISE) {
max_players = 1;
} else if (game_type == GAME_MULTIPLAYER) {
max_players = 10;
} else if (game_type == GAME_FRIENDS) {
max_players = 50;
}
let db = admin.database();
let gamesRef = db.ref("/games");
gamesRef.push({
... // data to be inserted
}).then(res => {
return {
"status": 200,
"id": gamesRef.key
}
}).catch(error => {
return {
"status": 403,
"id": null
}
});
}
});
You're missing a return here:
return gamesRef.push({
... // data to be inserted
}).then(res => {
return {
"status": 200,
"id": gamesRef.key
}
}).catch(error => {
return {
"status": 403,
"id": null
}
});
Without that top-level return, nobody will ever see the return values from your then and catch callbacks.

How to traverse all files, and support pause and continue

I have created a NodeJS (electron) code for read all the files in a specific directory and subdirectories.
I don't want to use too much HD resources, that why I use a delay of 5ms between folders.
Now my question. I want the if my NODE process stop? I want to be able to continue from when it is stopped. How should I do that?
In other words: How to keep index of current state while walking in all files and folder, so I can continue the traversing from when it has stopped.
Thank you
My Code:
var walkAll=function(options){
var x=0
walk(options.dir,function(){})
function walk(dir,callback) {
var files=fs.readdirSync(dir);
var stat;
async.eachSeries(files,function(file,next){
file=dir +'/' + file
if (dir.match(/Recycle/)) return next()
if (dir.match(/.git/)) return next()
if (dir.match(/node_modules/)) return next()
fs.lstat(file,function(err,stat){
if(err) return next()
if(stat.mode==41398) return next()
if (stat.isDirectory()) {
setTimeout(function(file){
walk(file,next)
}.bind(null,file),5)
}
else{
x++
if(false || x % 1000===0) console.log((new Date().valueOf()-start)/1000,x,file)
next()
}
})
},function(){
callback()
})
}
}
walkAll({
dir:'c:/',
delay:1000
});
Keep a list of sub directories to be visited, and update the list every iteration.
The walk function in the following example takes a previous state, and returns files of next sub directory with next state.
You can save the state before stopping the process, then load the saved state to continue the traversal when restarting.
function walk(state, readdir) {
let files = [], next = [];
while (state.length > 0) {
try {
const current = state.shift()
files = readdir(current).map(file => current + '/' + file)
next = state.concat(files)
break
} catch(e) {}
}
return [next, files]
}
function main() {
const {writeFileSync: writeFile, readdirSync: readdir} = require('fs')
const save = './walk.json'
let state
try {
state = require(save)
} catch(e) {}
if (!state || state.length < 1) state = ['.']
const [nextState, files] = walk(state, readdir)
console.log(files)
writeFile(save, JSON.stringify(nextState, null, 2))
}
main()
an alternate idea,
var miss = require('mississippi')
var fs = require("fs")
var through2 = require("through2")
var path = require("path")
function traverseDir(dirPath) {
var stack = [path.resolve(dirPath)];
var filesStack = []
return miss.from.obj(function(size, next) {
if (filesStack.length) {
return next(null, filesStack.shift())
}
var self = this;
try {
while(stack.length) {
readADir(stack.pop()).forEach(function (f) {
if (f.t=="d") {
stack.push(f.p)
}
filesStack.push(f)
})
if (filesStack.length) {
return next(null, filesStack.shift())
}
}
return next(null, null)
}catch(ex) {
return next(ex)
}
})
}
function readADir (dir) {
return fs.readdirSync(dir)
.map(function (f) {return path.join(dir, f)})
.filter(function (f) { return !f.match(/\.git/) })
.filter(function (f) { return !f.match(/Recycle/)})
.filter(function (f) { return !f.match(/node_modules/)})
.map(function (p) {
try {
var stat = fs.lstatSync(p);
if(stat.mode==41398) return null
var t = stat.isDirectory() ? "d":"f"
return { t: t, p: p }
}catch (ex) {}
return null
})
.filter(function (o) {return o!==null})
}
function loadState(base){
base = path.resolve(base)
var state = {base: base, last:null}
if (fs.existsSync("state.json")) {
state = JSON.parse(fs.readFileSync("state.json"))
} else {
saveState(state)
}
return state
}
function saveState(state){
fs.writeFileSync("state.json", JSON.stringify(state))
}
var state = loadState("..")
var sincePath = state.last;
var filesStream = traverseDir(state.base)
.on('end', function () {
console.log("end")
})
.pipe(through2.obj(function (chunk, enc, next) {
if(!sincePath) this.push(chunk)
if(chunk.p===sincePath) {
sincePath=null
}
next()
}))
var tr = through2.obj(function (chunk, enc, next) {
state.last = chunk.p
saveState(state)
console.log("data %v %j", chunk.t, chunk.p)
this.push(chunk)
setTimeout(next, 500)
}).resume()
require('keypress')(process.stdin);
process.stdin.on('keypress', function (ch, key) {
if(!key) return
if (key.name == "c") {
console.log("continue")
filesStream.pipe(tr)
} else if (key.name=="p") {
console.log("pause")
filesStream.unpipe(tr)
}
});
console.log("Press 'c' to start")

Node.js - TypeError: Object #<Object> has no method

I am trying to include a module i found that will help manage users:
http://www.codeproject.com/Articles/382561/Session-Management-in-Nodejs
Ive copied the code and put it in the same directory as my server.js
I require it by doing:
var express = require('express');
var http = require('http'),
mysql = require("mysql");
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var sessionMgm = require("./sessionManagement");
Now in my socket i do this:
io.sockets.on('connection', function (socket) {
socket.on('setUserInfo', function (data) {
var sess = new Object();
sess.sessionId = socket.id;
sess.userId = data.userId;
sess.username = data.username;
sess.role = data.role;
sessionMgm.add(sess);
});
socket.on("private", function(data) {
if(data.agentName.length <= 0) {
data.agentName = 'Besökare';
}
io.sockets.in('Room_' + data.user_id).emit('updatechat', data.agentName, data.msg);
var user = sessionMgm.getSessionByUserId(data.id);
console.log('::: A socket with ID ' + user + ' connected! ::: ');
});
});
However i keep getting this error:
TypeError: Object # has no method 'getSessionByUserId'
Cant seem to figure out whats wrong, any ideas?
sessionManagement.js:
module.exports = sessionManagement;
var sessions = [];
//User roles list
var userRoles = {
Admin: "administrator",
User: "user",
Supervisor: "supervisor"
};
var sessionManagement = {
indexOf: function(sessionId) {
for(var i in sessions) {
if(sessions[i].sessionId == sessionId)
return i;
}
return null;
},
indexOfUser: function(userId) {
for(var i in sessions) {
if(sessions[i].userId == userId)
return i;
}
return null;
},
add: function(sessionData) {
sessions.push(sessionData);
},
remove: function(sessionId) {
var index = this.indexOf(sessionId);
if(index != null) {
sessions.splice(index, 1);
} else {
return null;
}
},
removeByUserId: function(userId) {
var index = this.indexOf(userId);
if(index != null) {
sessions.splice(index, 1);
} else {
return null;
}
},
getSessionById: function(userId) {
var index = this.indexOfUser(userId);
if(index != null) {
return sessions[index];
} else {
return null;
}
},
getSessionByUserId: function(sessionId) {
var index = this.indexOfUser(userId);
if(index != null) {
return sessions[index];
} else {
return null;
}
},
isAdmin: function(userId) {
var index = this.indexOfUser(userId);
if(index != null) {
if(users[index].role == userRoles.Admin) {
return true;
} else {
return false;
}
} else {
return null;
}
},
getUsersByRole: function(role) {
var usersByRole = [];
for(var i in users) {
if(users[i].role == role)
usersByRole.push(users[i]);
}
return usersByRole;
}
};
As madflow mentioned, you were missing module.exports = sessionManagement in sessionManagement.js
Then you got the error, because you were exporting sessionManagement, before initializing it. Moving the export line to the end of sessionManagement.js should fix that.
module.exports = sessionManagement; // <- you export here
...
...
...
var sessionManagement = { // and initialize here
Although sessionManagement declaration gets hoisted to the top of the module (and that's why you don't get Unexpected identifier or ReferenceError when assigning it to module.exports), it's initialization does not, so what really happens behind the scenes is something like that:
var sessionManagement; // undefined at this point
module.exports = sessionManagement; // <- you export here,
// but sessionManagement is undefined at this point
// and so will be module.exports after this line
...
...
...
sessionManagement = { // and initialize here

Resources