Skip to content
Snippets Groups Projects
Commit 807a7009 authored by Lucendio's avatar Lucendio
Browse files

[app/server] Introduce a test for creating a user document in the database

* introduce a test on the server to see if user creation works (backend process <-> db only;
  still needs a test that involves the router, too)
* main server process is no connection-aware and wont start if database is not reachable
* some renaming, cause it's more descriptive
* unify quote usage
parent 08b36521
No related branches found
No related tags found
No related merge requests found
PORT=3000
MONGODB_URL=mongodb://localhost:27017/todo-app
JWT_SECRET=myjwtsecret
module.exports = {
testEnvironment: 'node'
};
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -5,10 +5,13 @@
"license": "MIT",
"scripts": {
"start": "node src/index",
"dev": "env-cmd -f ./dev.env nodemon src/index"
"dev": "env-cmd -f ./dev.env nodemon src/index",
"test": "env-cmd -f ./dev.env jest --ci"
},
"devDependencies": {
"@shelf/jest-mongodb": "^1.1.5",
"env-cmd": "^10.1.0",
"jest": "^25.1.0",
"nodemon": "^2.0.2"
},
"dependencies": {
......
const mongoose = require('mongoose');
const mongooseInstance_ = mongoose.connect(process.env.MONGODB_URL, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
// NOTE: as of the docs `connectTimeoutMS` should be used when `useUnifiedTopology: true`,
// but apparently it has no impact what so ever. Instead, the following works ¯\_(ツ)_/¯
serverSelectionTimeoutMS: 7000 // 7 sec
});
module.exports = mongooseInstance_;
const mongoose = require('mongoose')
mongoose.connect(process.env.MONGODB_URL, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true
})
const path = require( 'path' );
const express = require('express')
const cors = require('cors')
const helmet = require('helmet')
require('./db/mongoose')
const todoRoutes = require('./routes/todo-routes')
const userRoutes = require('./routes/user-routes')
const errorRoutes = require('./routes/error-routes')
let cookieParser = require('cookie-parser')
const app = express()
const port = process.env.PORT || 5000
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const dbClientInstance_ = require('./db/mongo.js');
const todoRoutes = require('./routes/todo');
const userRoutes = require('./routes/user');
const errorRoutes = require('./routes/error');
let cookieParser = require('cookie-parser');
const app = express();
const port = process.env.PORT || 5000;
const corsOptions = {
origin: `http://localhost:${ port }`,
credentials: true
}
};
app.use(express.json())
app.use(cors(corsOptions))
app.use(express.json());
app.use(cors(corsOptions));
app.use(cookieParser())
app.use(cookieParser());
app.use(helmet())
app.use(helmet());
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self' 'unsafe-inline'"],
scriptSrc: ["'self' 'unsafe-inline' 'unsafe-eval'"]
}
}))
}));
app.use(todoRoutes)
app.use(userRoutes)
app.use(todoRoutes);
app.use(userRoutes);
app.use('/', express.static(path.join(__dirname,`./../../client/build`)));
app.use(errorRoutes)
app.listen(port, () => {
console.log('ToDo server is up on port ' + port)
})
app.use(errorRoutes);
(async function main(){
try{
const dbClient = await dbClientInstance_;
process.on( 'exit', ()=>{
dbClient.disconnect();
});
await new Promise( (__ful, rej__ )=>{
app.listen(port, function(){
console.log( `ToDo server is up on port ${ port }`);
__ful();
}).on( 'error', rej__);
});
}catch(e){
console.error( new Error( `Cannot connect to database ${ process.env.MONGODB_URL }` ) );
process.exit( 1 );
}
})();
const jwt = require('jsonwebtoken')
const Users = require('../models/Users-model')
const { model: Users } = require('../models/Users')
const auth = async (req, res, next) => {
try {
......
const mongoose = require("mongoose")
const mongoose = require('mongoose');
const ToDosSchema = new mongoose.Schema({
const schema = new mongoose.Schema({
title: {
type: String,
required: true,
......@@ -23,9 +24,9 @@ const ToDosSchema = new mongoose.Schema({
}
}, {
timestamps: true
})
});
const ToDos = mongoose.model('ToDos', ToDosSchema)
const model = mongoose.model( 'ToDos', schema );
module.exports = ToDos
module.exports = { schema, model };
const dbClientInstance_ = require( './../db/mongo.js' );
const { model: Users } = require( './Users.js' );
describe( 'Model: Users', ()=>{
beforeAll( async ()=>{
await dbClientInstance_;
});
const userData = {
name: 'myname',
email: 'myname@example.com',
password: 'mypassword'
};
test( 'creating a user', async ()=>{
const userData = {
name: 'myname',
email: 'myname@example.com',
password: 'mypassword'
};
const userDoc = await Users( userData );
await userDoc.save();
const userRecord = await Users.findOne({ email: userData.email });
const { password, ...userInfo } = userData;
expect( userRecord ).toEqual( expect.objectContaining( userInfo ) );
});
afterAll( async ()=>{
const dbClient = await dbClientInstance_;
const { connection } = dbClient;
await connection.dropDatabase();
await dbClient.disconnect();
});
});
const mongoose = require("mongoose")
const validator = require('validator')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const usersSchema = new mongoose.Schema({
const schema = new mongoose.Schema({
name: {
type: String,
required: true,
......@@ -16,7 +17,7 @@ const usersSchema = new mongoose.Schema({
required: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error("Invalid email format")
throw new Error('Invalid email format');
}
}
},
......@@ -34,59 +35,58 @@ const usersSchema = new mongoose.Schema({
}]
}, {
timestamps: true
})
});
usersSchema.pre('save', async function (next) {
const user = this
schema.pre('save', async function (next) {
const user = this;
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
user.password = await bcrypt.hash(user.password, 8);
}
next()
})
next();
});
usersSchema.statics.findByCredentials = async (email, password) => {
const user = await Users.findOne({ email })
schema.statics.findByCredentials = async (email, password) => {
const user = await Users.findOne({ email });
if (!user) {
throw new Error('Unable to login')
throw new Error('Unable to login');
}
const isMatch = await bcrypt.compare(password, user.password)
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw new Error('Unable to login')
throw new Error('Unable to login');
}
return user
}
return user;
};
usersSchema.methods.generateAuthToken = async function () {
schema.methods.generateAuthToken = async function () {
const user = this
const user = this;
const token = jwt.sign({ _id: user._id.toString() }, process.env.JWT_SECRET)
const token = jwt.sign({ _id: user._id.toString() }, process.env.JWT_SECRET);
user.tokens = user.tokens.concat({ token })
user.tokens = user.tokens.concat({ token });
await user.save()
await user.save();
return token
}
return token;
};
usersSchema.methods.toJSON = function () {
const user = this
const publicUserData = user.toObject()
schema.methods.toJSON = function () {
const user = this;
const publicUserData = user.toObject();
delete publicUserData.password
delete publicUserData.tokens
delete publicUserData.password;
delete publicUserData.tokens;
return publicUserData
}
const Users = mongoose.model('Users', usersSchema)
const model = mongoose.model( 'Users', schema );
module.exports = Users
module.exports = { schema, model };
......@@ -6,7 +6,7 @@ routes.get('*', async (req, res) => {
try {
res.status(404).send({
error: "Invalid endpoint."
error: 'Not Found'
})
}
catch (e) {
......@@ -15,4 +15,4 @@ routes.get('*', async (req, res) => {
})
module.exports = routes
\ No newline at end of file
module.exports = routes
const express = require('express')
const ToDos = require('../models/Todos-model')
const { model: ToDos } = require('../models/Todos')
const auth = require('../middlewares/auth')
const routes = express.Router()
......@@ -53,11 +53,11 @@ routes.patch('/todo/update', auth, async (req, res) => {
return res.status(400).send({ error: 'Invalid fields to update!' })
}
const updateObj = {}
if (changedTodo.hasOwnProperty("important")) {
if (changedTodo.hasOwnProperty('important')) {
updateObj.important = changedTodo.important
}
if (changedTodo.hasOwnProperty("done")) {
if (changedTodo.hasOwnProperty('done')) {
updateObj.done = changedTodo.done
}
......
const express = require('express')
const Users = require('../models/Users-model')
const { model: Users } = require('../models/Users')
const auth = require('../middlewares/auth')
const routes = express.Router()
......@@ -77,4 +77,4 @@ routes.post('/logout', auth, async (req, res) => {
}
})
module.exports = routes
\ No newline at end of file
module.exports = routes
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment