Increased unit test coverage of controllers

This commit is contained in:
Chris Troutner
2021-07-11 21:59:18 -07:00
parent 4cdb389706
commit 43b2b9dfdf
5 changed files with 207 additions and 54 deletions
+9 -36
View File
@@ -11,60 +11,33 @@ const User = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
validate: {
validator: function (email) {
// eslint-disable-next-line no-useless-escape
return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)
},
message: props => `${props.value} is not a valid Email format!`
}
unique: true
}
})
// Before saving, convert the password to a hash.
User.pre('save', function preSave (next) {
User.pre('save', async function preSave (next) {
const user = this
if (!user.isModified('password')) {
return next()
}
new Promise((resolve, reject) => {
bcrypt.genSalt(10, (err, salt) => {
if (err) {
return reject(err)
}
resolve(salt)
})
})
.then(salt => {
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
throw new Error(err)
}
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(user.password, salt)
user.password = hash
user.password = hash
next(null)
})
})
.catch(err => next(err))
next(null)
})
// Validate the password by comparing to the saved hash.
User.methods.validatePassword = function validatePassword (password) {
User.methods.validatePassword = async function validatePassword (password) {
const user = this
return new Promise((resolve, reject) => {
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) {
return reject(err)
}
const isMatch = await bcrypt.compare(password, user.password)
resolve(isMatch)
})
})
return isMatch
}
// Generate a JWT token.
+6 -18
View File
@@ -110,25 +110,13 @@ class JSONRPC {
// The default JSON RPC response if the incoming command could not be routed.
defaultResponse () {
try {
// const errorObj = this.jsonrpc.error(
// 'Can not route',
// new jsonrpc.JsonRpcError('Input does not match routing rules', 422)
// )
// const errorStr = JSON.stringify(errorObj)
// return errorStr
const errorObj = {
success: false,
status: 422,
message: 'Input does not match routing rules.'
}
return errorObj
} catch (err) {
console.error('Error in defaultResponse()')
throw err
const errorObj = {
success: false,
status: 422,
message: 'Input does not match routing rules.'
}
return errorObj
}
}
+82
View File
@@ -0,0 +1,82 @@
/*
Unit tests for the users Mongoose model.
*/
const assert = require('chai').assert
const sinon = require('sinon')
const mongoose = require('mongoose')
// Set the environment variable to signal this is a test.
process.env.SVC_ENV = 'test'
const User = require('../../../src/adapters/localdb/models/users')
const config = require('../../../config')
describe('#User-Adapter', () => {
// let uut
let sandbox
let testuser
before(async () => {
// Connect to the Mongo Database.
console.log(`Connecting to database: ${config.database}`)
mongoose.Promise = global.Promise
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
await mongoose.connect(config.database, {
useUnifiedTopology: true,
useNewUrlParser: true
})
testuser = new User({
email: 'test983@test.com',
name: 'test983',
password: 'password'
})
})
beforeEach(async () => {
sandbox = sinon.createSandbox()
})
afterEach(() => sandbox.restore())
after(async () => {
await testuser.remove()
mongoose.connection.close()
})
describe('#save', () => {
it('should replace the password with a salt', async () => {
await testuser.save()
// console.log('testuser: ', testuser)
assert.notEqual(testuser.password, 'password')
})
})
describe('#validatePassword', () => {
it('should return true when password matches', async () => {
const result = await testuser.validatePassword('password')
// console.log('result: ', result)
assert.equal(result, true)
})
it('should return false when password does not match', async () => {
const result = await testuser.validatePassword('wrongpassword')
// console.log('result: ', result)
assert.equal(result, false)
})
})
describe('#generateToken', () => {
it('should generate a JWT token', () => {
const token = testuser.generateToken()
// console.log('token: ', token)
assert.include(token, 'eyJ')
})
})
})
+37
View File
@@ -0,0 +1,37 @@
/*
Unit tests for controllers index.js file.
*/
// Public npm libraries
// const assert = require('chai').assert
const sinon = require('sinon')
const adapters = require('../../../src/adapters')
const { attachControllers } = require('../../../src/controllers')
describe('#Controllers', () => {
// let uut
let sandbox
beforeEach(() => {
sandbox = sinon.createSandbox()
})
afterEach(() => sandbox.restore())
describe('#attachControllers', () => {
it('should attach the controllers', async () => {
// mock IPFS
sandbox.stub(adapters.ipfs, 'start').resolves({})
adapters.ipfs.ipfsCoordAdapter = {
attachRPCRouter: () => {}
}
const app = {
use: () => {}
}
await attachControllers(app)
})
})
})
@@ -29,6 +29,34 @@ describe('#JSON RPC', () => {
afterEach(() => sandbox.restore())
describe('#constructor', () => {
it('should throw an error if adapters are not passed in', () => {
try {
uut = new JSONRPC()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Adapters library required when instantiating JSON RPC Controllers.'
)
}
})
it('should throw an error if useCases are not passed in', () => {
try {
uut = new JSONRPC({ adapters })
assert.fail('Unexpected code path')
} catch (err) {
assert.include(
err.message,
'Instance of Use Cases library required when instantiating JSON RPC Controllers.'
)
}
})
})
describe('#router', () => {
it('should exit quietly if given a random string', async () => {
const str = 'random string message'
@@ -106,5 +134,50 @@ describe('#JSON RPC', () => {
assert.equal(obj.result.method, 'users')
assert.equal(obj.id, id)
})
it('should route to auth handler', async () => {
const id = uid()
const userCall = jsonrpc.request(id, 'auth', { endpoint: 'getAll' })
const jsonStr = JSON.stringify(userCall, null, 2)
// Mock the controller.
sandbox.stub(uut.authController, 'authRouter').resolves('true')
const result = await uut.router(jsonStr, 'peerA')
// console.log(result)
const obj = JSON.parse(result.retStr)
// console.log('obj: ', obj)
assert.equal(obj.result.value, 'true')
assert.equal(obj.result.method, 'auth')
assert.equal(obj.id, id)
})
it('should route to about handler', async () => {
const id = uid()
const userCall = jsonrpc.request(id, 'about', { endpoint: 'getAll' })
const jsonStr = JSON.stringify(userCall, null, 2)
// Mock the controller.
sandbox.stub(uut.aboutController, 'aboutRouter').resolves('true')
// Force ipfs-coord communication.
uut.ipfsCoord.ipfs = {
orbitdb: {
sendToDb: () => {}
}
}
const result = await uut.router(jsonStr, 'peerA')
// console.log(result)
const obj = JSON.parse(result.retStr)
// console.log('obj: ', obj)
assert.equal(obj.result.value, 'true')
assert.equal(obj.result.method, 'about')
assert.equal(obj.id, id)
})
})
})