diff --git a/.env.production b/.env.production index 9d7f924..bfbee07 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,5 @@ DATABASE =FreePlanet -TEST_ATTIVO=1 +SEND_EMAIL=1 PORT=3000 URLBASE_APP1=https://freeplanet.app PORT_APP1="0" @@ -7,9 +7,8 @@ DOMAIN=mongodb://localhost:27017/ SIGNCODE=abc123 EMAIL_FROM=perseo774.un@gmail.com EMAIL_PW=passpao1UNOK -SEND_EMAIL="1" -DEBUG=true +DEBUG=0 PATH_CERT_KEY=/etc/letsencrypt/live/freeplanet.app/privkey.pem PATH_SERVER_CRT=/etc/letsencrypt/live/freeplanet.app/fullchain.pem -PUBLIC_VAPI_KEY=BGxRrFWnPoa_ImUaWXmeEOFVI9VNKVKaAPsvsM1XY6wn24yxp9MyOQ4crNYCJKxSXV65Y1GblW5_VLoamedcZ1I -PRIVATE_VAPI_KEY=aDtJfPsXTQgA1GiLAAhs1ilNCJWxncgO-p2b591L-9o +PUBLIC_VAPI_KEY=BJGWIAlFXXQWqdBIEujrDJ7ZQeQmcwTOXr1kPfYy2ZCI6hvV9jhfquW2uHVoOiSYpoF6HeqnaydsIV5SeEpFbCk +PRIVATE_VAPI_KEY=40Cn-P-j8iPs5RRR4VsH2lgmYSXqA5xK-nppK_HCbgA diff --git a/package.json b/package.json index 0b7c3a3..fb243fa 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,19 @@ { "name": "freeplanet-serverside", - "version": "1.0.0", - "description": "", - "main": "index.js", + "version": "1.0.1", + "description": "freeplanet serverside", + "main": "server.js", "scripts": { "start": "nodemon server/server.js", "test": "export NODE_ENV=development || SET NODE_ENV=development && mocha server/**/*.test.js", "start:prod": "NODE_ENV=production node server/server.js", - "test-watch": "nodemon --exec 'npm test'", - "startpush": "node server/webpush.js" + "test-watch": "nodemon --exec 'npm test'" }, "engines": { "node": "6.2.2" }, - "author": "", - "license": "ISC", + "author": "Paolo Arena", + "license": "MIT", "dependencies": { "bcrypt": "^3.0.2", "body-parser": "^1.15.2", diff --git a/server/config/config.js b/server/config/config.js index 40a38d2..6c2fef8 100644 --- a/server/config/config.js +++ b/server/config/config.js @@ -15,3 +15,6 @@ require('dotenv').config({path: file}); process.env.DATABASE = process.env.DATABASE || 'FreePlanet'; process.env.MONGODB_URI = process.env.DOMAIN + process.env.DATABASE; + +// console.log("priv", process.env.PRIVATE_VAPI_KEY); +// console.log("pub", process.env.PUBLIC_VAPI_KEY); diff --git a/server/db/mongoose.js b/server/db/mongoose.js index a72ea7c..8992146 100644 --- a/server/db/mongoose.js +++ b/server/db/mongoose.js @@ -2,7 +2,14 @@ var mongoose = require('mongoose'); mongoose.Promise = global.Promise; -mongoose.level = "F"; +mongoose.level = ""; + +mongoose.plugin(schema => { + schema.options.usePushEach = true +}); + +mongoose.set('debug', false); + mongoose.connect(process.env.MONGODB_URI, { useMongoClient: true, promiseLibrary: require('bluebird') }) .then(() => console.log('connection succesful ' + process.env.MONGODB_URI + ' db: ' + process.env.DATABASE) diff --git a/server/models/user.js b/server/models/user.js index c1dcec2..4f6c15a 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -4,7 +4,6 @@ const validator = require('validator'); const jwt = require('jsonwebtoken'); const _ = require('lodash'); - mongoose.Promise = global.Promise; mongoose.level = "F"; @@ -50,7 +49,7 @@ var UserSchema = new mongoose.Schema({ }, linkreg: { type: String, - required: true + required: false }, verified_email: { type: Boolean, diff --git a/server/router/email_router.js b/server/router/email_router.js index b7d618d..171a7a1 100644 --- a/server/router/email_router.js +++ b/server/router/email_router.js @@ -1,6 +1,8 @@ const express = require('express'); const router = express.Router(); +var {User} = require('../models/user'); + router.get('/:email', (req, res) => { var email = req.params.email; diff --git a/server/router/index_router.js b/server/router/index_router.js index 67b3dc0..dc93d71 100644 --- a/server/router/index_router.js +++ b/server/router/index_router.js @@ -1,6 +1,13 @@ const express = require('express'); const router = express.Router(); +const _ = require('lodash'); + +var {User} = require('../models/user'); + +var server_constants = require('../tools/server_constants'); + + router.post(process.env.LINKVERIF_REG, (req, res) => { var body = _.pick(req.body, ['idapp', 'idlink']); var idapp = body.idapp; @@ -50,7 +57,7 @@ router.post(process.env.LINK_REQUEST_NEWPASSWORD, (req, res) => { user.tokenforgot = jwt.sign(user._id.toHexString(), process.env.SIGNCODE).toString(); user.date_tokenforgot = new Date(); user.save().then(() => { - sendemail.sendEmail_RequestNewPassword(getlang(res), user.email, user.idapp, user.tokenforgot); + sendemail.sendEmail_RequestNewPassword(res.locale, user.email, user.idapp, user.tokenforgot); res.send({ code: server_constants.RIS_CODE_OK, msg: '' }); }); } diff --git a/server/router/subscribe_router.js b/server/router/subscribe_router.js index 72e9b5c..402f674 100644 --- a/server/router/subscribe_router.js +++ b/server/router/subscribe_router.js @@ -5,20 +5,23 @@ const Subscription = mongoose.model('subscribers'); const webpush = require('web-push'); router.post('/', (req, res) => { - const subscriptionModel = new Subscription(req.body.subs); - subscriptionModel.save((err, subscription) => { - if (err) { - console.error(`Error occurred while saving subscription. Err: ${err}`); - res.status(500).json({ - error: 'Technical error occurred' - }); - } else { - // Send 201 - resource created - res.status(201).json({ data: 'Subscription saved.' }); + console.log('req.body.others', req.body.others); + let subscriptionModel = new Subscription(req.body.subs); + subscriptionModel.userId = req.body.others.userId - sendBackNotif(subscription, req.body.options) - } - }); + subscriptionModel.save((err, subscription) => { + if (err) { + console.error(`Error occurred while saving subscription. Err: ${err}`); + res.status(500).json({ + error: 'Technical error occurred' + }); + } else { + // Send 201 - resource created + res.status(201).json({ data: 'Subscription saved.' }); + + sendBackNotif(subscription, req.body.options) + } + }); }); function sendBackNotif(subscription, payload) { @@ -30,11 +33,10 @@ function sendBackNotif(subscription, payload) { } - router.get('/', (req, res) => { - res.json({ - data: 'Invalid Request Bad' - }); + res.json({ + data: 'Invalid Request Bad' + }); }); module.exports = router; diff --git a/server/router/todos_router.js b/server/router/todos_router.js index 557fdf8..839778d 100644 --- a/server/router/todos_router.js +++ b/server/router/todos_router.js @@ -4,6 +4,9 @@ const webpush = require('web-push'); var { authenticate } = require('../middleware/authenticate'); +var mongoose = require('mongoose'); +const Subscription = mongoose.model('subscribers'); + var { Todo } = require('../models/todo'); const _ = require('lodash'); @@ -28,7 +31,7 @@ router.post('/:id', authenticate, (req, res) => { console.log('RECORD NON VALIDO !?', req.body) } - sendNotificationToUser('New Post', 'New Post added!', '/' + todo.category); + sendNotificationToUser(todo.userId, 'New Todo', 'New Todo added!', '/' + todo.category, 'todo'); todo.save().then((doc) => { res.send(doc); @@ -38,6 +41,78 @@ router.post('/:id', authenticate, (req, res) => { }); }); + +function sendNotificationToUser(userId, title, content, openUrl, tag) { + + const payload = { + title: title, + message: content, + url: openUrl, + tag, + // ttl: req.body.ttl, + // icon: req.body.icon, + // image: req.body.image, + // badge: req.body.badge, + // tag: req.body.tag + }; + + Subscription.find({userId: userId}, (err, subscriptions) => { + if (err) { + console.error(`Error occurred while getting subscriptions`); + res.status(500).json({ + error: 'Technical error occurred' + }); + } else { + let parallelSubscriptionCalls = subscriptions.map((subscription) => { + return new Promise((resolve, reject) => { + const pushSubscription = { + endpoint: subscription.endpoint, + keys: { + p256dh: subscription.keys.p256dh, + auth: subscription.keys.auth + } + }; + + const pushPayload = JSON.stringify(payload); + const pushOptions = { + vapidDetails: { + subject: process.env.URLBASE_APP1, + privateKey: process.env.PRIVATE_VAPI_KEY, + publicKey: process.env.PUBLIC_VAPI_KEY, + }, + TTL: payload.ttl, + headers: {} + }; + webpush.sendNotification( + pushSubscription, + pushPayload, + pushOptions + ).then((value) => { + resolve({ + status: true, + endpoint: subscription.endpoint, + data: value + }); + }).catch((err) => { + reject({ + status: false, + endpoint: subscription.endpoint, + data: err + }); + }); + }); + }); + // q.allSettled(parallelSubscriptionCalls).then((pushResults) => { + // console.info(pushResults); + // }); + // res.json({ + // data: 'Push triggered' + // }); + } + }); + +} + router.patch('/:id', authenticate, (req, res) => { var id = req.params.id; var body = _.pick(req.body, allfieldTodo); @@ -52,7 +127,7 @@ router.patch('/:id', authenticate, (req, res) => { return res.status(404).send(); } - todo.modified = false + todo.modified = false; res.send({todo}); }).catch((e) => { @@ -60,25 +135,6 @@ router.patch('/:id', authenticate, (req, res) => { }) }); -function sendNotificationToUser(title, content, openUrl) { - - // Create payload - const payload = JSON.stringify( - { - title, - content, - openUrl - } - ); - - subscriptioncfg = {}; - - // Pass object into sendNotification - - webpush.sendNotification(subscriptioncfg, payload).catch(err => console.error(err)); - -} - router.get('/:userId', authenticate, (req, res) => { diff --git a/server/router/users_router.js b/server/router/users_router.js index ab32f7a..a5fe313 100644 --- a/server/router/users_router.js +++ b/server/router/users_router.js @@ -3,49 +3,65 @@ const router = express.Router(); var { User } = require('../models/user'); +var sendemail = require('../sendemail'); + +var server_constants = require('../tools/server_constants'); + const _ = require('lodash'); +var reg = require('../reg/registration'); + var { authenticate } = require('../middleware/authenticate'); +function testing() { + return (process.env.TESTING_ON === '1') +} + +function mylog(...args) { + if (!testing()) + console.log(args) +} + +function mylogshow(...args) { + console.log(args) +} // POST /users router.post('/', (req, res) => { - console.log("POST /users"); + mylog("POST /users"); var body = _.pick(req.body, ['email', 'password', 'username', 'idapp', 'keyappid', 'lang']); var user = new User(body); - // console.log("LANG PASSATO = " + user.lang); - // console.log("IDAPP = " + user.idapp); + // mylog("LANG PASSATO = " + user.lang, "IDAPP", user.idapp); user.linkreg = reg.getlinkregByEmail(body.email, body.username); user.verified_email = false; + if (testing()) { + user.verified_email = true; + } user.save().then(() => { User.findByUsername(user.username) .then((usertrovato) => { - //console.log("USERNAME : " + user.username); - //console.log("TROVATO USERNAME ? " + usertrovato); + + mylog("TROVATO USERNAME ? ", user.username, usertrovato); if (usertrovato !== null) { - //console.log("Non esiste ancora"); - // Non esiste ancora, allora genero il TOKEN ! return user.generateAuthToken(); } else { - //console.log("Esiste già! Quindi non creo lo user."); - // Esiste già! Quindi non creo lo user. res.status(11100).send(); return 0; } }).then((token) => { - // passo il token in x-auth - //console.log("USER"); - //console.log(user); - console.log("TOKEN: "); - console.log(token); + // mylog("passo il TOKEN: ", token); res.header('x-auth', token).send(user); - console.log("LINKREG = " + user.linkreg); + // mylog("LINKREG = " + user.linkreg); // Invia un'email all'utente - sendemail.sendEmail_Registration(getlang(res), user.email, user.username, user.idapp, user.linkreg); + // mylog('process.env.TESTING_ON', process.env.TESTING_ON); + if (!testing()) { + sendemail.sendEmail_Registration(res.locale, user.email, user.username, user.idapp, user.linkreg); + } + }); }).catch((e) => { res.status(400).send(e); @@ -70,18 +86,19 @@ router.post('/login', (req, res) => { var body = _.pick(req.body, ['username', 'password', 'idapp', 'keyappid', 'lang']); var user = new User(body); - console.log("user: " + user.username + " pwd = " + user.password); + mylogshow("username: " + user.username + " pwd = " + user.password); + + mylogshow("user REC:", user); if (body.keyappid !== process.env.KEY_APP_ID) - // Se non faccio la richesa con la IDAPP giusta, allora esco! return res.status(400).send(); User.findByCredentials(user.username, user.password) .then((user) => { - console.log("CREDENZIALI ! "); + mylogshow("CREDENZIALI ! "); if (!user) { - console.log("NOT FOUND !"); + mylogshow("NOT FOUND !"); res.status(404).send({ code: server_constants.RIS_CODE_LOGIN_ERR }); } else { return user.generateAuthToken().then((token) => { @@ -91,23 +108,23 @@ router.post('/login', (req, res) => { usertosend.userId = user._id.toHexString(); usertosend.verified_email = user.verified_email; - // console.log("user.verified_email:" + user.verified_email); - // console.log("usertosend.userId", usertosend.userId); + // mylog("user.verified_email:" + user.verified_email); + // mylog("usertosend.userId", usertosend.userId); - // console.log("usertosend:"); - // console.log(usertosend); + // mylog("usertosend:"); + // mylog(usertosend); res.header('x-auth', token).send(usertosend); - // console.log("TROVATOOO!"); + // mylog("TROVATOOO!"); }); } }).catch((e) => { - console.log("ERR: " + e); + mylog("ERR: " + e); res.status(400).send({ code: server_constants.RIS_CODE_LOGIN_ERR_GENERIC }); }); }); router.delete('/me/token', authenticate, (req, res) => { - console.log("TOKENREM = " + req.token); + mylog("TOKENREM = " + req.token); req.user.removeToken(req.token).then(() => { res.status(200).send(); }, () => { diff --git a/server/server.js b/server/server.js index 0267330..5e322af 100644 --- a/server/server.js +++ b/server/server.js @@ -26,9 +26,6 @@ require('./models/todo'); require('./models/user'); require('./models/subscribers'); -const { ObjectID } = require('mongodb'); - - const index_router = require('./router/index_router'); const push_router = require('./router/push_router'); const subscribe_router = require('./router/subscribe_router'); @@ -42,11 +39,6 @@ console.log("DB: " + process.env.DATABASE); console.log("PORT: " + port); console.log("MONGODB_URI: " + process.env.MONGODB_URI); -var sendemail = require('./sendemail'); -var reg = require('./reg/registration'); -var tools = require('./tools/general'); -var server_constants = require('./tools/server_constants'); - var app = express(); // app.use(express.static(path.join(__dirname, 'client'))); @@ -72,16 +64,15 @@ app.use(bodyParser.json()); app.use(i18n.init); +// SETTINGS WebPush Configuration const webpush = require('web-push'); const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const privateVapidKey = process.env.PRIVATE_VAPI_KEY; - webpush.setVapidDetails('mailto:' + process.env.EMAIL_FROM, publicVapidKey, privateVapidKey); // Use Routes - app.use('/', index_router); app.use('/subscribe', subscribe_router); app.use('/push', push_router); @@ -89,7 +80,6 @@ app.use('/email', email_router); app.use('/todos', todos_router); app.use('/users', users_router); - // catch 404 and forward to error handler app.use(function (req, res, next) { var err = new Error('Not Found'); @@ -105,7 +95,7 @@ app.use(function (req, res, next) { // will print stacktrace if (app.get('env') === 'development') { app.use(function (err, req, res, next) { - console.log('Error: ', err.message) + console.log('Error: ', err.message); // console.trace(); res.status(err.status || 500).send({error: err.message}); // res.render('error', { @@ -115,13 +105,6 @@ if (app.get('env') === 'development') { }); } - -function getlang(res) { - return res.locale; -} - - - if (process.env.NODE_ENV === 'production') { var httpsServer = https.createServer(credentials, app); console.log("httpsServer: port ", port); @@ -136,19 +119,5 @@ if (process.env.NODE_ENV === 'production') { // console.log(`Server started at port ${port}`); //}); - module.exports = { app }; -if (process.env.TEST_ATTIVO) { - eseguitest(); -} - -function eseguitest() { - - if (false) { - console.log("ESEGUI I TEST:"); - console.log("linkreg = " + sendemail.getlinkReg(1, "myusername")); - } - - // sendemail.sendEmail_Registration("en", "paolo.arena77@gmail.com", "paoloar77", 1, "http://provalink.com"); -} diff --git a/server/tests/seed/seed.js b/server/tests/seed/seed.js new file mode 100644 index 0000000..64f5f9b --- /dev/null +++ b/server/tests/seed/seed.js @@ -0,0 +1,94 @@ +const { ObjectID } = require('mongodb'); +const jwt = require('jsonwebtoken'); + +const { Todo } = require('./../../models/todo'); +const { User } = require('./../../models/user'); + +var bcrypt = require('bcrypt'); + +const userOneId = new ObjectID(); +const userTwoId = new ObjectID(); +const userThreeId = new ObjectID(); + +// let mypwdchiaro = 'mypassword@1A'; +// let mypwdcrypt = bcrypt.hash(mypwdchiaro, bcrypt.genSaltSync(12)) +// .then((hashedPassword) => { +// console.log('pwd=',hashedPassword); +// }); +// String(mypwdcrypt) + +let mypwdcrypted = '$2b$12$mteST.isuWO0SNsfeZ0aCe.Dz3qwPh5SU8t9rc5SaPTkb3j0ywGv6' + +const users = [ { + _id: userTwoId, + keyappid: process.env.KEY_APP_ID, + lang: 'it', + idapp: '1', + email: 'paoloa.rena77@gmail.com', + username: 'paoloar77B', + password: mypwdcrypted, + tokens: [{ + access: 'auth', + token: jwt.sign({ _id: userOneId, access: 'auth' }, process.env.SIGNCODE).toString() + }] +}, + { + _id: userThreeId, + keyappid: process.env.KEY_APP_ID, + lang: 'it', + idapp: '1', + email: 'pa@com', + password: mypwdcrypted, + username: 'paoloar77C', + tokens: [{ + access: 'auth', + token: jwt.sign({ _id: userTwoId, access: 'auth' }, process.env.SIGNCODE).toString() + }] + }, { + keyappid: process.env.KEY_APP_ID, + lang: 'it', + idapp: '1', + email: 'pao.loarena77@gmail.com', + password: mypwdcrypted, + username: 'paoloar77A' + }]; + +const userjson = JSON.stringify(users[0]); + +// console.log('userjson=', userjson) + + +const todos = [{ + _id: new ObjectID(), + text: 'First test todo', + _creator: userOneId +}, { + _id: new ObjectID(), + text: 'Second test todo', + completed: true, + completedAt: 333, + _creator: userTwoId +}]; + +const populateTodos = (done) => { + const lista = [ users[0]._id, users[1]._id, users[2]._id]; + Todo.deleteMany({ userId: {$in: lista } }) + .then(() => { + return Todo.insertMany(todos); + }).then(() => done()) +}; + +const populateUsers = (done) => { + const lista = [ users[0].username, users[1].username, users[2].username]; + // const lista = [ "aa"] + User.deleteMany({ username: {$in: lista } }) + .then(() => { + + var userOne = new User(users[0]).save(); + var userTwo = new User(users[1]).save(); + + return Promise.all([userOne, userTwo]) + }).then(() => done()); +}; + +module.exports = { todos, populateTodos, users, populateUsers, userjson, mypwdcrypted }; diff --git a/server/tests/server.test.js b/server/tests/server.test.js new file mode 100644 index 0000000..48eda06 --- /dev/null +++ b/server/tests/server.test.js @@ -0,0 +1,437 @@ +const expect = require('expect'); +const request = require('supertest'); +const { ObjectID } = require('mongodb'); + +const { app } = require('./../server'); +const { Todo } = require('./../models/todo'); +const { User } = require('./../models/user'); +const { todos, populateTodos, users, populateUsers, userjson } = require('./seed/seed'); + +// const { debug } = require('debug'); +// const log = debug('server'); + +let jsonUser1 = { + email: "paolo.arena77@gmail.com", + password: "$2a$12$hTv40mdq.x35Up7HQ9faae1JgHrohcvp45vt8eMkGhQv/Zv.8.MIG", + username: "paoloar77", + idapp: "1", + lang: "it", + keyappid: "KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF" +}; + +beforeEach(populateUsers); +beforeEach(populateTodos); + +const IndexUserToCreate = 2; + +// console.log('UserOne:', users[0]); +// console.log('UserTwo:', users[0]); + +// console.log('userjson', userjson); + +describe('POST /users', () => { + it('should create a user', (done) => { + request(app) + .post('/users') + .send(users[IndexUserToCreate]) + .expect(200) + .expect((res) => { + expect(res.headers['x-auth']).toExist(); + expect(res.body._id).toExist(); + expect(res.body.email).toBe(users[IndexUserToCreate].email); + expect(res.body.username).toBe(users[IndexUserToCreate].username); + }) + .end((err) => { + if (err) { + console.log('ERR:', err); + return done(err); + } + + User.findOne({ email: users[IndexUserToCreate].email }).then((user) => { + expect(user).toExist(); + done(); + }).catch((e) => done(e)); + }); + }); + + it('should return validation errors if request invalid', (done) => { + request(app) + .post('/users') + .send({ + email: 'and', + password: '123' + }) + .expect(400) + .end(done); + }); + + it('should not create user if email in use', (done) => { + request(app) + .post('/users') + .send(users[1]) + .expect(400) + .end(done); + }); +}); + +describe('GET /users/myusername', () => { + it('should return 200 if myusername exist', (done) => { + request(app) + .get('/users/' + users[0].username) + // .set('x-auth', users[0].tokens[0].token) + .expect(200) + .end(done); + }); + + it('should return 404 if myusername doesn\'t exist', (done) => { + request(app) + .get('/users/' + users[0].username + 'pippo') + .expect(404) + .end(done); + }); +}); + +describe('POST /users/login', () => { + it('should login user and return auth token', (done) => { + request(app) + .post('/users/login') + .set('x-auth', users[0].tokens[0].token) + .send({ + username: users[0].username, + password: users[0].password, + idapp: users[0].idapp, + keyappid: users[0].keyappid, + lang: users[0].lang, + }) + .expect(200) + .expect((res) => { + expect(res.headers['x-auth']).toExist(); + }) + .end((err, res) => { + if (err) { + return done(err); + } + + User.findById(users[0]._id).then((user) => { + expect(user.tokens[0]).toInclude({ + access: 'auth', + token: res.headers['x-auth'] + }); + done(); + }).catch((e) => done(e)); + }); + }); +/* + it('should reject invalid login', (done) => { + request(app) + .post('/users/login') + .send({ + email: users[1].email, + password: users[1].password + '1' + }) + .expect(400) + .expect((res) => { + expect(res.headers['x-auth']).toNotExist(); + }) + .end((err, res) => { + if (err) { + return done(err); + } + + User.findById(users[1]._id).then((user) => { + expect(user.tokens.length).toBe(1); + done(); + }).catch((e) => done(e)); + }); + }); + */ +}); + + + + + + + +describe('POST /todos', () => { + /* + it('should create a new Todos', (done) => { + request(app) + .post('/todos') + .set('x-auth', users[0].tokens[0].token) + .send(users[0]) + .expect(200) + .expect((res) => { + expect(res.body.text).toBe(text); + }) + .end((err, res) => { + if (err) { + return done(err); + } + + Todo.find({ text }).then((todos) => { + expect(todos.length).toBe(1); + expect(todos[0].text).toBe(text); + done(); + }).catch((e) => done(e)); + }); + }); + */ +}) + +/* + + it('should not create todo with invalid body data', (done) => { + request(app) + .post('/todos') + .set('x-auth', users[0].tokens[0].token) + .send({}) + .expect(400) + .end((err, res) => { + if (err) { + return done(err); + } + + Todo.find().then((todos) => { + expect(todos.length).toBe(2); + done(); + }).catch((e) => done(e)); + }); + }); +}); + +describe('GET /todos', () => { + it('should get all todos', (done) => { + request(app) + .get('/todos') + .set('x-auth', users[0].tokens[0].token) + .expect(200) + .expect((res) => { + expect(res.body.todos.length).toBe(1); + }) + .end(done); + }); +}); + +describe('GET /todos/:id', () => { + it('should return todo doc', (done) => { + request(app) + .get(`/todos/${todos[0]._id.toHexString()}`) + .set('x-auth', users[0].tokens[0].token) + .expect(200) + .expect((res) => { + expect(res.body.todo.text).toBe(todos[0].text); + }) + .end(done); + }); + + it('should not return todo doc created by other user', (done) => { + request(app) + .get(`/todos/${todos[1]._id.toHexString()}`) + .set('x-auth', users[0].tokens[0].token) + .expect(404) + .end(done); + }); + + it('should return 404 if todo not found', (done) => { + var hexId = new ObjectID().toHexString(); + + request(app) + .get(`/todos/${hexId}`) + .set('x-auth', users[0].tokens[0].token) + .expect(404) + .end(done); + }); + + it('should return 404 for non-object ids', (done) => { + request(app) + .get('/todos/123abc') + .set('x-auth', users[0].tokens[0].token) + .expect(404) + .end(done); + }); +}); + +describe('DELETE /todos/:id', () => { + it('should remove a todo', (done) => { + var hexId = todos[1]._id.toHexString(); + + request(app) + .delete(`/todos/${hexId}`) + .set('x-auth', users[1].tokens[0].token) + .expect(200) + .expect((res) => { + expect(res.body.todo._id).toBe(hexId); + }) + .end((err, res) => { + if (err) { + return done(err); + } + + Todo.findById(hexId).then((todo) => { + expect(todo).toNotExist(); + done(); + }).catch((e) => done(e)); + }); + }); + + it('should remove a todo', (done) => { + var hexId = todos[0]._id.toHexString(); + + request(app) + .delete(`/todos/${hexId}`) + .set('x-auth', users[1].tokens[0].token) + .expect(404) + .end((err, res) => { + if (err) { + return done(err); + } + + Todo.findById(hexId).then((todo) => { + expect(todo).toExist(); + done(); + }).catch((e) => done(e)); + }); + }); + + it('should return 404 if todo not found', (done) => { + var hexId = new ObjectID().toHexString(); + + request(app) + .delete(`/todos/${hexId}`) + .set('x-auth', users[1].tokens[0].token) + .expect(404) + .end(done); + }); + + it('should return 404 if object id is invalid', (done) => { + request(app) + .delete('/todos/123abc') + .set('x-auth', users[1].tokens[0].token) + .expect(404) + .end(done); + }); +}); + +describe('PATCH /todos/:id', () => { + it('should update the todo', (done) => { + var hexId = todos[0]._id.toHexString(); + var text = 'This should be the new text'; + + request(app) + .patch(`/todos/${hexId}`) + .set('x-auth', users[0].tokens[0].token) + .send({ + completed: true, + text + }) + .expect(200) + .expect((res) => { + expect(res.body.todo.text).toBe(text); + expect(res.body.todo.completed).toBe(true); + expect(res.body.todo.completedAt).toBeA('number'); + }) + .end(done); + }); + + it('should not update the todo created by other user', (done) => { + var hexId = todos[0]._id.toHexString(); + var text = 'This should be the new text'; + + request(app) + .patch(`/todos/${hexId}`) + .set('x-auth', users[1].tokens[0].token) + .send({ + completed: true, + text + }) + .expect(404) + .end(done); + }); + + it('should clear completedAt when todo is not completed', (done) => { + var hexId = todos[1]._id.toHexString(); + var text = 'This should be the new text!!'; + + request(app) + .patch(`/todos/${hexId}`) + .set('x-auth', users[1].tokens[0].token) + .send({ + completed: false, + text + }) + .expect(200) + .expect((res) => { + expect(res.body.todo.text).toBe(text); + expect(res.body.todo.completed).toBe(false); + expect(res.body.todo.completedAt).toNotExist(); + }) + .end(done); + }); +}); + +describe('GET /users/me', () => { + it('should return user if authenticated', (done) => { + request(app) + .get('/users/me') + .set('x-auth', users[0].tokens[0].token) + .expect(200) + .expect((res) => { + expect(res.body._id).toBe(users[0]._id.toHexString()); + expect(res.body.email).toBe(users[0].email); + }) + .end(done); + }); + + it('should return 401 if not authenticated', (done) => { + request(app) + .get('/users/me') + .expect(401) + .expect((res) => { + expect(res.body).toEqual({}); + }) + .end(done); + }); +}); + +describe('DELETE /users/me/token', () => { + it('should remove auth token on logout', (done) => { + request(app) + .delete('/users/me/token') + .set('x-auth', users[0].tokens[0].token) + .expect(200) + .end((err, res) => { + if (err) { + return done(err); + } + + User.findById(users[0]._id).then((user) => { + expect(user.tokens.length).toBe(0); + done(); + }).catch((e) => done(e)); + }); + }); +}); + + +// sendemail.sendEmail_Registration("en", "paolo.arena77@gmail.com", "paoloar77", 1, "http://provalink.com"); + + +*/ + +/* +describe('slow test', function() { + + // Tests will be considered slow after 1 second elapses + this.slow(1000); + + // Completes after the specified 1 second elapses + it('should be complete in a second', function(done) { + setTimeout(done, 1500); + }) + + // Completes immediately + it('should be complete instantly', function() {}) + +}) +*/