Mongoose save function doesn't execute - node.js

I am trying to save my model into the my db in MongoDB. This code actually works if I were to go through this code path when running the node server, however when I try to use mocha to test saving the model it doesn't get saved anymore. I have verified that the connection to mongodb is fine. Thia is the output:
before regular save
after regular save
Any tips or suggestions would be greatly appreciated. thanks!
This is the test I am running.
var app = require('./helpers/app');
var User = require('../models/user');
var supertest = require('supertest');
var should = require('should');
var mongoose = require('mongoose');
var MongoUrl = require('./../config.js').mongoUri
var clearDB = require('mocha-mongoose')(MongoUrl);
var testuser = {
username:"admin1",
password:"password",
email:"test#gmail.com",
firstname:"testfirst",
lastname:"testlast",
phonenumber:"4151231234"
};
describe("Routing", function() {
describe("Creating an account", function() {
//To run before each test. DB Clean up is implicitly done after each test.
beforeEach(function(done) {
if (mongoose.connection.db) {
return done();
}
mongoose.connect(dbURI, done);
});
it('User: Creating an account2', function(done){
var newUser = new User({
username: "testusername",
email: "test1#gmail.com",
password: "password",
phoneNumber: "12312312",
firstname: "testfirst",
lastname: "testlast"
});
console.log("before regular save");
newUser.save(function(err){
if(err){
console.log("testerror: " + err);
}
console.log("in regular save");
});
console.log("after regular save");
User.find({}, function(err, docs){
if (err) return done(err);
console.log(docs);
docs.length.should.equal(1);
done();
});
});
});
});

Model#save is an async function so you have to wait until it calls its callback before you can expect to be able to find the saved doc with a Model.find call.
So put the find check inside the save callback:
it('User: Creating an account2', function(done){
var newUser = new User({
username: "testusername",
email: "test1#gmail.com",
password: "password",
phoneNumber: "12312312",
firstname: "testfirst",
lastname: "testlast"
});
console.log("before regular save");
newUser.save(function(err){
if(err){
console.log("testerror: " + err);
return done(err);
}
console.log("in regular save");
console.log("after regular save");
User.find({}, function(err, docs){
if (err) return done(err);
console.log(docs);
docs.length.should.equal(1);
done();
});
});
});

Related

MongoDB update if user not exists

I have a problem to update user if his/her name is not available in my database
I thought if my function "User.findOne" doesn't find a user in my mongodb it can update database. Unfortunately nothing happens. I get only output "Hello Anna you are new here!" My name is not saved into my mongodb
Could somebody smart give me please a tip how can I save username if it is not in my database
var User = require('./user');
var myName = this.event.request.intent.slots.first_name.value;
self = this;
User.findOne({ name: myName }, function(err, user) {
if (err ||!user){
var userSave = new User({
name: myName
});
userSave.save(function (err, results) {
console.log(results);
self.emit(':ask',
"Hello "+ myName +"you are new here!")
});
}
else {
self.emit(':ask',
"Hello "+ myName +" you are not new!")
}
});
My mongoose model code:
//user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect("mongodb://c******mlab.com:***/users");
var userSchema = new Schema({
name: String,
userId: { type: String, required: false, unique: true }
});
var User = mongoose.model('User', userSchema);
module.exports = User;
var User = require('./user');
var myName = this.event.request.intent.slots.first_name.value;
self = this;
User.findOne({
name: myName
}, (err, user) => {
if(err) throw err;
if(user) {
self.emit(':ask', `Hello ${myName} you are not new`);
} else {
User.create({
name: myName
}, (err, result) => {
if(err) throw err;
console.log(result);
self.emit(':ask', `Hello ${myName} you are new here!`);
})
}
});
this should work.
The line if (err || !user) is confusing to read, and in this style you're mixing error handling (if (err)) and a condition in your code that you expect to hit (if (!user)). I suggest you separate them so the code is easier to read and debug.
For example, using plain Javascript and the MongoDB node driver:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost/test', function(err, conn) {
// connection error handling
if (err) {
console.log('Connection error: ' + err);
}
conn.db('test').collection('test').findOne({name:'abc'}, function(err, doc) {
// findOne error handling
if (err) {
console.log('Error: ' + err);
}
// if document exists
if (doc) {
console.log('Document found: ' + JSON.stringify(doc));
}
// if document doesn't exist
else {
console.log('Document not found');
}
conn.close();
});
});
If the database contains the user abc, the output would be:
$ node script.js
Document not found
If the user abc exists:
$ node script.js
Document found: {"_id":0,"name":"abc"}
I believe using a similar pattern you can modify your code to do what you need.

pre function not called in mongoose

I am trying to encrypt password on registration using mongoose and mongodb but pre function is not called at all.
var mongoose = require('mongoose');
var Schema = mongoose.Schema,
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10;
var patientSchema = new Schema({
username: {type: String, trim: true, index: { unique: true }},
password: {type: String, required: true}
});
//====================== Middleware:Start==========================//
patientSchema.pre('save', function(next) {
console.log('pre called'); //This is not printed at all
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password along with our new salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
//======================Middleware:End===========================//
//======================API Routes:Start===========================//
router.route('/signup')
.post(function (req, res) {
console.log('post signup called', req.body);
var patients = new Patients({
username: req.body.username,
password: req.body.password
});
Patients.findOne({username: req.body.username}, function (err, user) {
if (err) {
console.log('user not found');
}
if (user) {
console.log("patient already exists");
res.json({message: 'patient already exists'});
} else {
//Saving the model instance to the DB
patients.save(function (err) {
if (err)
throw err;
console.log("user Saved Successfully");
res.json({message: 'user Saved Successfully'});
});
}
});
});
module.exports = router;
//======================API Routes:End===========================//
Inside the pre function, console.log('pre called'); is not printed at all. What am I missing here?
it might be solve your error.
const patients = new Patients({
username: req.body.username,
password: req.body.password
})
if(!patients) return res.json(patients)
patients.save((err,patients) => {
if(err) return res.json({status: 500, message: err})
return res.json({status: 200, user: patients})
})
Thank you.

Mocha route testing not executing asynchronously

I have started working with mocha and I have a problem with one particular test case. Here is the code:
var assert = require("chai").assert;
var request = require('supertest');
var http = require("http");
var conf = require("../config/config");
var app = require("../app");
var mongoose = require('mongoose');
var User = mongoose.model('User');
describe('User controller', function(){
describe('POST /register', function(){
it('should return false when the parameters are not unique', function (done) {
request(app)
.post('/user/register')
.send({username:"janette_doe", email:"janette_doe#gmail.com", password:"test123"})
.expect('Content-Type',/json/)
.expect({success:true, redirect:'/user/registerConfirmation'})
.end(function(err, res) {
if (err) {
return done(err);
}
request(app)
.post('/user/register')
.send({username:"janette_doe", email:"janette_doe#gmail.com", password:"test123"})
.expect('Content-Type',/json/)
.expect({success:false}, done);
});
});
});
I am expecting the result to be false because after the insertion of a user inside the database, the unique index rule should raise an error. When I run this test, I get this: {success: true, redirect: '/user/registerConfirmation'} , I should be getting this: {success: false}. I noticed that when I don't clear the database before each tests (in utils.js) I am getting the expected value. Do I get this error because of an asynchronous error? How can I rewrite this test to make sure that it works?
Thanks
Files
util.js contains the configurations for the test sequence:
'use strict';
process.env.NODE_ENV = 'test';
var config = require('../config/config');
var mongoose = require('mongoose');
beforeEach(function (done) {
mongoose.connection.db.dropDatabase();
return done();
});
afterEach(function (done) {
return done();
});
user.js the user model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
var UserSchema = new Schema({
username: {type: String, required: true, unique: true},
email: {type: String, required: true, unique: true},
password: {type: String, required: true},
status: {type: Number, default:0}
});
UserSchema.virtual('date')
.get(function(){
return this._id.getTimestamp();
});
UserSchema.pre('save', function(next) {
//Password encryption ...
});
mongoose.model('User', UserSchema);
user.js (controller) is the controller for all the user routes.
...
router.post('/register', function (req,res,next){
var newUser = new User({
username: req.body.username
, email: req.body.email
, password: req.body.password
});
newUser.save(function(err){
if(err){
res.send({success: false});
}else{
var newToken = new UserToken({
userId: newUser._id
, email: newUser.email
});
newToken.save(function(err){
if(err){
res.send({success: false});
}else{
res.send({success: true, redirect: '/user/registerConfirmation'});
}
});
}
});
});
...
Edit
I have tried the end() function and it still doesn't work.
There is a problem in how you chain supertest requests in your test test suite - the second request is not invoked properly. When you were not clearing the database the test was failing on the first .expect({success: true, ...}) and you were getting the expected value.
The correct way is to perform the first request with .end method, check for potential errors, and then perform the second request to see if it has failed:
describe('User controller', function(){
describe('POST /register', function(){
it('should return false when the parameters are not unique', function (done) {
request(app)
.post('/user/register')
.send({username:"janette_doe", email:"janette_doe#gmail.com", password:"test123"})
.expect('Content-Type',/json/)
.expect({success:true, redirect:'/user/registerConfirmation'})
.end(function(err, res) {
// Check if first request has failed (it should not!)
if (err) {
return done(err);
}
// Testing the second, not unique request. that should fail
request(app)
.post('/user/register')
.send({username:"janette_doe", email:"janette_doe#gmail.com", password:"test123"})
.expect('Content-Type',/json/)
.expect({success:false}, done);
});
});
});
In mocha, the done() function should be called when your async call is done - regardless of whether an error is hit. Also, use the .done() function - which is part of the promise API - to end the promise chain and ensure any exceptions are caught. Without the done function, you can miss runtime errors completely, as they are suppressed by the promise library.

mongoosejs find specific record

i want to find a specific record in mongoose. i'm trying to make a login/register form and im kind of new to node.js..
for now i have this code:
app.post('/register', function(request, response)
{
console.log('REGISTER OK');
//set connection to mongodb.
mongoose.connect('mongodb://localhost');
var db = mongoose.connection;
//Connect to mongodb.
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback()
{
console.log('connection succeed.');
//Create User schema.
var userSchema = mongoose.Schema(
{
username: String,
password: String
});
//User model.
var UserModel = mongoose.model('User', userSchema);
var user = new UserModel(
{
username: request.body.username,
password: request.body.password
});
user.save(function(error, data)
{
if(error)
console.log(error);
else
{
response.render('register',
{
'Title': Title,
'result': data
});
UserModel.find(function(error, data)
{
if(error)
console.log(error);
else
console.log(data);
});
}
});
});
});
i dont quite get the find method of mongoose, i just need to find the username in order to do some function, is there a function that moongose has to avoid record if this exists already?
UserModel.findOne ({ name: "someName" }, function (err, user) {
if (err) console.log (err);
if (!user) console.log ('user not found');
// do something with user
});

how to get all users in redis

I have the following code .
var redis = require("redis"),
client = redis.createClient();
user_rahul = {
username: 'rahul'
};
user_namita = {
username: 'namita'
};
client.hmset('users.rahul', user_rahul);
client.hmset('users.namita', user_namita);
var username = "rahul"; // From a POST perhaps
client.hgetall("users" , function(err, user) {
console.log(user);
});
I want to get all the users list how i can get all users list this what i tried but its not working.
You are setting the users in their own hash, so when you do hgetall users, you are trying to get all the members of the users hash. You should do:
var redis = require("redis"),
client = redis.createClient();
user_rahul = {
username: 'rahul'
};
user_namita = {
username: 'namita'
};
client.hset('users', user_rahul, 'Another Value, Pass Maybe?');
client.hset('users', user_namita, 'Another Value, Pass Maybe?');
var username = "rahul"; // From a POST perhaps
client.hgetall("users" , function(err, user) {
console.log(user);
});
You should consider using a list instead, if you dont need any data in the second hash value
How about this
var flow = require('flow'); //for async calls
var redis = require("redis").createClient();
function AddUser(user,callback){
flow.exec(
function(){
//AI for Keep unique
redis.incr('nextUserId',this);
},
function(err,userId){
if(err) throw err;
this.userId = userId;
redis.lpush('users',userId,this.MULTI());
redis.hmset('user:'+userId+':profile',user,MULTI());
},
function(results){
results.forEach(function(result){
if(result[0]) throw result[0];
});
callback(this.userId);
}
);
}
user_rahul = {username: 'rahul'};
user_namita = {username: 'namita'};
//Add user
AddUser(user_rahul,function(userId){
console.log('user Rahul Id' + userId);
});
AddUser(user_namita,function(userId){
console.log('user Namita Id' + userId);
});
//users
function Users(callback){
var users = [];
flow.exec(
function(){
redis.lrange('users',0,-1,this);
},
function(err,userIds){
if(err) throw err;
flow.serialForEach(userIds,function(userId){
redis.hgetall('user:'+userId+':profile',this);
},
function(err,val){
if(err) throw err;
users.push(val);
},
function(){
callback(users);
});
}
);
}
//call
Users(function(users){
console.log(users);
});
For Single User
function getUser(userId,callback){
redis.hgetall('user:'+ userId +':profile',function(err,profile){
if(err) throw err;
callback(profile);
});
}
getUser(1,function(profile){
console.log(profile);
});

Resources