feat(admin): Increased code coverage of lib/admin.js

This commit is contained in:
Daniel Gonzalez
2020-11-22 18:43:01 -04:00
parent 7067b56c7f
commit d9172dd4f6
4 changed files with 246 additions and 109 deletions
+4 -1
View File
@@ -12,7 +12,10 @@ const cors = require('kcors')
// Local libraries // Local libraries
const config = require('../config') // this first. const config = require('../config') // this first.
const adminLib = require('../src/lib/admin')
const AdminLib = require('../src/lib/admin')
const adminLib = new AdminLib()
const errorMiddleware = require('../src/middleware') const errorMiddleware = require('../src/middleware')
const wlogger = require('../src/lib/wlogger') const wlogger = require('../src/lib/wlogger')
+108 -96
View File
@@ -23,125 +23,137 @@ const JSON_PATH = `${__dirname}/../../config/${JSON_FILE}`
const LOCALHOST = `http://localhost:${config.port}` const LOCALHOST = `http://localhost:${config.port}`
const context = {} const context = {}
// Create the first user in the system. A 'admin' level system user that is let _this
// used by the Listing Manager and test scripts, in order access private API class Admin {
// functions. constructor () {
async function createSystemUser () { this.axios = axios
// Create the system user. this.User = User
try { this.config = config
context.password = _randomString(20) this.jsonFiles = jsonFiles
this.context = context
const options = { _this = this
method: 'POST', }
url: `${LOCALHOST}/users`,
data: { // Create the first user in the system. A 'admin' level system user that is
user: { // used by the Listing Manager and test scripts, in order access private API
email: 'system@system.com', // functions.
password: context.password async createSystemUser () {
// Create the system user.
try {
context.password = _this._randomString(20)
const options = {
method: 'POST',
url: `${LOCALHOST}/users`,
data: {
user: {
email: 'system@system.com',
password: context.password
}
} }
} }
} const result = await _this.axios.request(options)
const result = await axios(options) context.email = result.data.user.email
context.id = result.data.user._id
context.token = result.data.token
context.email = result.data.user.email // Get the mongoDB entry
context.id = result.data.user._id const user = await _this.User.findById(context.id)
context.token = result.data.token
// Get the mongoDB entry // Change the user type to admin
const user = await User.findById(context.id) user.type = 'admin'
// console.log(`user created: ${JSON.stringify(user, null, 2)}`)
// Change the user type to admin // Save the user model.
user.type = 'admin' await user.save()
// console.log(`user: ${JSON.stringify(user, null, 2)}`)
// Save the user model. // console.log(`admin user created: ${JSON.stringify(result.body, null, 2)}`)
await user.save() // console.log(`with password: ${context.password}`)
// console.log(`admin user created: ${JSON.stringify(result.body, null, 2)}`) // Write out the system user information to a JSON file that external
// console.log(`with password: ${context.password}`) // applications like the Task Manager and the test scripts can access.
// Write out the system user information to a JSON file that external await jsonFiles.writeJSON(context, JSON_PATH)
// applications like the Task Manager and the test scripts can access.
await jsonFiles.writeJSON(context, JSON_PATH)
return context return context
} catch (err) { } catch (err) {
// Handle existing system user. // Handle existing system user.
if (err.response.status === 422) { if (err.response.status === 422) {
try { try {
// Delete the existing user // Delete the existing user
await deleteExistingSystemUser() await _this.deleteExistingSystemUser()
// Call this function again. // Call this function again.
return createSystemUser() return _this.createSystemUser()
} catch (err2) { } catch (err2) {
console.error('Error in admin.js/createSystemUser() while trying generate new system user.') console.error('Error in admin.js/createSystemUser() while trying generate new system user.')
// process.end(1)
throw err2
}
} else {
console.log('Error in admin.js/createSystemUser: ')
// process.end(1) // process.end(1)
throw err2 throw err
} }
} else { }
console.log('Error in admin.js/createSystemUser: ' + JSON.stringify(err, null, 2)) }
// process.end(1)
async deleteExistingSystemUser () {
try {
mongoose.Promise = global.Promise
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
await mongoose.connect(config.database, { useNewUrlParser: true, useUnifiedTopology: true })
await _this.User.deleteOne({ email: 'system@system.com' })
} catch (err) {
console.log('Error in admin.js/deleteExistingSystemUser()')
throw err throw err
} }
} }
}
async function deleteExistingSystemUser () { async loginAdmin () {
try { // console.log(`loginAdmin() running.`)
mongoose.Promise = global.Promise let existingUser
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
await mongoose.connect(config.database, { useNewUrlParser: true, useUnifiedTopology: true }) try {
// Read the exising file
existingUser = await _this.jsonFiles.readJSON(JSON_PATH)
// console.log(`existingUser: ${JSON.stringify(existingUser, null, 2)}`)
await User.deleteOne({ email: 'system@system.com' }) // Log in as the user.
} catch (err) { const options = {
console.log('Error in admin.js/deleteExistingSystemUser()') method: 'POST',
throw err url: `${LOCALHOST}/auth`,
} headers: {
} Accept: 'application/json'
},
async function loginAdmin () { data: {
// console.log(`loginAdmin() running.`) email: 'system@system.com',
let existingUser password: existingUser.password
}
try {
// Read the exising file
existingUser = await jsonFiles.readJSON(JSON_PATH)
// console.log(`existingUser: ${JSON.stringify(existingUser, null, 2)}`)
// Log in as the user.
const options = {
method: 'POST',
url: `${LOCALHOST}/auth`,
data: {
email: 'system@system.com',
password: existingUser.password
} }
const result = await _this.axios.request(options)
// console.log(`result1: ${JSON.stringify(result, null, 2)}`)
return result
} catch (err) {
console.error('Error in admin.js/loginAdmin().')
// console.error(`existingUser: ${JSON.stringify(existingUser, null, 2)}`)
throw err
} }
const result = await axios(options) }
// console.log(`result1: ${JSON.stringify(result, null, 2)}`)
return result _randomString (length) {
} catch (err) { var text = ''
console.error('Error in admin.js/loginAdmin().') var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
for (var i = 0; i < length; i++) {
// console.error(`existingUser: ${JSON.stringify(existingUser, null, 2)}`) text += possible.charAt(Math.floor(Math.random() * possible.length))
}
throw err return text
} }
} }
function _randomString (length) { module.exports = Admin
var text = ''
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
for (var i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length))
}
return text
}
module.exports = {
createSystemUser,
loginAdmin
}
+18 -12
View File
@@ -1,17 +1,24 @@
const assert = require('chai').assert const assert = require('chai').assert
const PassportLib = require('../src/lib/passport') const PassportLib = require('../src/lib/passport')
describe('#passport.js', () => { const sinon = require('sinon')
let passportLib
beforeEach(async () => { let uut
passportLib = new PassportLib() let sandbox
describe('#passport.js', () => {
beforeEach(() => {
uut = new PassportLib()
sandbox = sinon.createSandbox()
}) })
afterEach(() => sandbox.restore())
describe('authUser()', () => { describe('authUser()', () => {
it('should throw error if ctx is not provided', async () => { it('should throw error if ctx is not provided', async () => {
try { try {
await passportLib.authUser() await uut.authUser()
assert(false, 'Unexpected result') assert(false, 'Unexpected result')
} catch (err) { } catch (err) {
assert.include(err.message, 'ctx is required') assert.include(err.message, 'ctx is required')
@@ -20,17 +27,16 @@ describe('#passport.js', () => {
it('Should throw error if the passport library fails', async () => { it('Should throw error if the passport library fails', async () => {
try { try {
// This is a mock to handle the callback error
// when the passport library fails or throws error
const error = new Error('cant auth user') const error = new Error('cant auth user')
const user = null const user = null
const authMock = (value, callback) => {
callback(error, user) // Mock calls
} // https://sinonjs.org/releases/latest/stubs/
passportLib.passport.authenticate = authMock // About yields
sandbox.stub(uut.passport, 'authenticate').yields(error, user)
const ctx = {} const ctx = {}
await passportLib.authUser(ctx) await uut.authUser(ctx)
assert(false, 'Unexpected result') assert(false, 'Unexpected result')
} catch (err) { } catch (err) {
assert.include(err.message, 'cant auth user') assert.include(err.message, 'cant auth user')
+116
View File
@@ -0,0 +1,116 @@
const assert = require('chai').assert
const Admin = require('../src/lib/admin')
const sinon = require('sinon')
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
let sandbox
let uut
describe('Admin', () => {
beforeEach(() => {
uut = new Admin()
sandbox = sinon.createSandbox()
})
afterEach(() => sandbox.restore())
describe('loginAdmin()', () => {
it('should logind admin', async () => {
try {
const error = new Error('test error')
error.response = {
status: 422
}
// sandbox.stub(uut.axios, 'request').onFirstCall().throws(error)
const result = await uut.loginAdmin()
const user = result.data.user
assert.property(user, '_id')
assert.property(user, 'email')
assert.property(user, 'type')
assert.isString(user._id)
assert.isString(user.email)
assert.isString(user.type)
assert.equal(user.type, 'admin')
} catch (err) {
assert(false, 'Unexpected result')
}
})
it('should handle axios error', async () => {
try {
// Returns an erroneous password to force
// an auth error
sandbox
.stub(uut.jsonFiles, 'readJSON').resolves({ password: 'wrong' })
await uut.loginAdmin()
assert(false, 'Unexpected result')
} catch (err) {
assert.equal(err.response.status, 401)
assert.include(err.response.data, 'Unauthorized')
}
})
})
describe('createSystemUser()', () => {
it('should create admin', async () => {
try {
const result = await uut.createSystemUser()
assert.property(result, 'email')
assert.property(result, 'password')
assert.property(result, 'id')
assert.property(result, 'token')
} catch (err) {
assert(false, 'Unexpected result')
}
})
it('should handle axios error', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
}
const error2 = new Error('test error')
error1.response = {
status: 500
}
// The loginAdmin() function in some use cases is recursive
// after handling the 422 error, it gets called again
sandbox
.stub(uut.axios, 'request')
.onFirstCall()
.throws(error1)
.onSecondCall()
.throws(error2)
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
})
it('should handle errors when remove user', async () => {
try {
const error1 = new Error('test error')
error1.response = {
status: 422
}
sandbox
.stub(uut.axios, 'request').throws(error1)
sandbox
.stub(uut.User, 'deleteOne').throws(new Error('test error'))
await uut.createSystemUser()
assert(false, 'Unexpected result')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
})