Got npm test working again

This commit is contained in:
Chris Troutner
2021-03-28 11:23:25 -07:00
parent 05441e153e
commit 21763d3fd2
10 changed files with 613 additions and 543 deletions
+8 -7
View File
@@ -5,15 +5,16 @@
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "export KOA_ENV=test && npm run prep-test && nyc --reporter=text mocha --exit --timeout 15000 test/unit/",
"test:unit:lib": "export KOA_ENV=test && npm run prep-test && nyc --reporter=text mocha --exit --timeout 15000 test/unit/biz-logic/",
"test:unit:rest": "export KOA_ENV=test && npm run prep-test && nyc --reporter=text mocha --exit --timeout 15000 test/unit/rest-api/",
"test:e2e:auto": "export KOA_ENV=test && npm run prep-test && nyc --reporter=text mocha --exit --timeout 15000 test/e2e/automated/",
"test": "npm run test:all",
"test:all": "npm run set-env && nyc --reporter=text mocha --exit --timeout 15000 test/unit/biz-logic/ test/unit/rest-api/ test/e2e/automated/",
"test:unit:lib": "npm run set-env && mocha --exit --timeout 15000 test/unit/biz-logic/",
"test:unit:rest": "npm run set-env && mocha --exit --timeout 15000 test/unit/rest-api/",
"test:e2e:auto": "npm run set-env && mocha --exit --timeout 15000 test/e2e/automated/",
"set-env": "export KOA_ENV=test",
"lint": "standard --env mocha --fix",
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
"coverage": "export KOA_ENV=test && npm run prep-test && nyc report --reporter=text-lcov | coveralls",
"coverage:report": "export KOA_ENV=test && npm run prep-test && nyc --reporter=html mocha --exit --timeout 15000 test/unit/",
"prep-test": "node util/users/delete-all-test-users.js"
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "npm run set-env && nyc --reporter=html mocha --exit --timeout 15000 test/unit/biz-logic/ test/unit/rest-api/ test/e2e/automated/"
},
"keywords": [
"koa-api-boilerplate",
+5 -1
View File
@@ -49,11 +49,14 @@ class Admin {
data: {
user: {
email: 'system@system.com',
password: context.password
password: context.password,
name: 'admin'
}
}
}
const result = await _this.axios.request(options)
// console.log('admin.data: ', result.data)
context.email = result.data.user.email
context.id = result.data.user._id
context.token = result.data.token
@@ -81,6 +84,7 @@ class Admin {
// Handle existing system user.
if (err.response.status === 422) {
try {
console.log('ping03')
// Delete the existing user
await _this.deleteExistingSystemUser()
+39 -38
View File
@@ -12,6 +12,45 @@ class UserLib {
this.UserModel = UserModel
}
// Create a new user model and add it to the Mongo database.
async createUser (userObj) {
try {
// Input Validation
if (!userObj.email || typeof userObj.email !== 'string') {
throw new Error("Property 'email' must be a string!")
}
if (!userObj.password || typeof userObj.password !== 'string') {
throw new Error("Property 'password' must be a string!")
}
if (!userObj.name || typeof userObj.name !== 'string') {
throw new Error("Property 'name' must be a string!")
}
const user = new this.UserModel(userObj)
// Enforce default value of 'user'
user.type = 'user'
// Save the new user model to the database.
await user.save()
// Generate a JWT token for the user.
const token = user.generateToken()
// Convert the database model to a JSON object.
const userData = user.toJSON()
// Delete the password property.
delete userData.password
return { userData, token }
} catch (err) {
// console.log('createUser() error: ', err)
wlogger.error('Error in lib/users.js/createUser()')
throw err
}
}
// Returns an array of all user models in the Mongo database.
async getAllUsers () {
try {
@@ -51,44 +90,6 @@ class UserLib {
throw err
}
}
// Create a new user model and add it to the Mongo database.
async createUser (userObj) {
try {
// Input Validation
if (!userObj.email || typeof userObj.email !== 'string') {
throw new Error("Property 'email' must be a string!")
}
if (!userObj.password || typeof userObj.password !== 'string') {
throw new Error("Property 'password' must be a string!")
}
if (!userObj.name && typeof userObj.name !== 'string') {
throw new Error("Property 'name' must be a string!")
}
const user = new this.UserModel(userObj)
// Enforce default value of 'user'
user.type = 'user'
// Save the new user model to the database.
await user.save()
// Generate a JWT token for the user.
const token = user.generateToken()
// Convert the database model to a JSON object.
const userData = user.toJSON()
// Delete the password property.
delete userData.password
return { userData, token }
} catch (err) {
wlogger.error('Error in lib/users.js/createUser()')
throw err
}
}
}
module.exports = UserLib
+6 -31
View File
@@ -9,10 +9,11 @@ const wlogger = require('../../lib/wlogger')
let _this
class UserController {
constructor () {
_this = this
// Encapsulate dependencies
this.User = User
this.userLib = new UserLib()
_this = this
}
/**
@@ -58,35 +59,9 @@ class UserController {
try {
const userObj = ctx.request.body.user
// /*
// * Input Validation
// */
// // Required property
// if (!userObj.email || typeof userObj.email !== 'string') {
// throw new Error("Property 'email' must be a string!")
// }
//
// if (!userObj.password || typeof userObj.password !== 'string') {
// throw new Error("Property 'password' must be a string!")
// }
//
// if (userObj.name && typeof userObj.name !== 'string') {
// throw new Error("Property 'name' must be a string!")
// }
//
// const user = new _this.User(userObj)
//
// // Enforce default value of 'user'
// user.type = 'user'
//
// await user.save()
//
// const token = user.generateToken()
// const response = user.toJSON()
//
// delete response.password
const { userData, token } = this.userLib.createUser(userObj)
const { userData, token } = await _this.userLib.createUser(userObj)
// console.log('userData: ', userData)
// console.log('token: ', token)
ctx.body = {
user: userData,
+19 -7
View File
@@ -1,10 +1,18 @@
const app = require('../../../bin/server')
const utils = require('../../utils/test-utils')
const config = require('../../../config')
const assert = require('chai').assert
/*
End-to-end tests for /auth endpoints.
This test sets up the environment for other e2e tests.
*/
// Public npm libraries
const assert = require('chai').assert
const axios = require('axios').default
// Local support libraries
const config = require('../../../config')
const app = require('../../../bin/server')
const testUtils = require('../../utils/test-utils')
// const request = supertest.agent(app.listen())
const context = {}
@@ -15,12 +23,16 @@ describe('Auth', () => {
// This should be the first instruction. It starts the REST API server.
await app.startServer()
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
const userObj = {
email: 'test@test.com',
password: 'pass'
password: 'pass',
name: 'test'
}
const testUser = await utils.createUser(userObj)
console.log('TestUser: ', testUser)
const testUser = await testUtils.createUser(userObj)
// console.log('TestUser: ', testUser)
context.user = testUser.user
context.token = testUser.token
+445 -442
View File
@@ -24,7 +24,8 @@ describe('Users', () => {
// Create a second test user.
const userObj = {
email: 'test2@test.com',
password: 'pass2'
password: 'pass2',
name: 'test2'
}
const testUser = await testUtils.createUser(userObj)
// console.log(`testUser2: ${JSON.stringify(testUser, null, 2)}`)
@@ -134,8 +135,9 @@ describe('Users', () => {
}
await axios(options)
assert(false, 'Unexpected result')
assert.fail('Unexpected result')
} catch (err) {
// console.log(err)
assert.equal(err.response.status, 422)
assert.include(err.response.data, "Property 'name' must be a string")
}
@@ -148,7 +150,8 @@ describe('Users', () => {
data: {
user: {
email: 'test3@test.com',
password: 'supersecretpassword'
password: 'supersecretpassword',
name: 'test3'
}
}
}
@@ -381,443 +384,443 @@ describe('Users', () => {
)
})
})
describe('PUT /users/:id', () => {
it('should not update user if token is invalid', async () => {
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/1`,
headers: {
Accept: 'application/json',
Authorization: 'Bearer 1'
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should throw 401 if non-admin updating other user', async () => {
const { token } = context
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/1`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should not be able to update user type', async () => {
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${context.user._id.toString()}`,
headers: {
Authorization: `Bearer ${context.token}`
},
data: {
user: {
name: 'new name',
type: 'test'
}
}
}
await axios(options)
// console.log(`Users: ${JSON.stringify(result.data, null, 2)}`)
// assert(result.status === 200, 'Status Code 200 expected.')
// assert(result.data.user.type === 'user', 'Type should be unchanged.')
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(
err.response.data,
"Property 'type' can only be changed by Admin user"
)
}
})
it('should not be able to update other user when not admin', async () => {
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
headers: {
Authorization: `Bearer ${context.token}`
},
data: {
user: {
name: 'This should not work'
}
}
}
await axios(options)
// console.log(`result: ${JSON.stringify(result.data, null, 2)}`)
assert(false, 'Unexpected result')
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should not be able to update if name property is wrong', async () => {
try {
const _id = context.user._id
const token = context.token
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
email: 'testToUpdate@test.com',
name: {}
}
}
}
await axios(options)
} catch (error) {
assert.equal(error.response.status, 422)
assert.include(error.response.data, "Property 'name' must be a string!")
}
})
it('should not be able to update if password property is not string', async () => {
const { token } = context
const _id = context.user._id
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
password: 1234
}
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(
err.response.data,
"Property 'password' must be a string!"
)
}
})
it('should not be able to update if project property is not array', async () => {
const { token } = context
const _id = context.user._id
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
projects: 'projects'
}
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(
err.response.data,
"Property 'projects' must be a Array!"
)
}
})
it('should not be able to update if email is not string', async () => {
const { token } = context
const _id = context.user._id
try {
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
email: 1234
}
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(err.response.data, "Property 'email' must be a string!")
}
})
it('should not be able to update if email is wrong format', async () => {
try {
const _id = context.user._id
const token = context.token
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
email: 'badEmailFormat'
}
}
}
await axios(options)
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(
err.response.data,
"Property 'email' must be email format!"
)
}
})
it('should not be able to update type property if is not string', async () => {
try {
const _id = context.user._id
const token = context.token
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
type: 1
}
}
}
await axios(options)
} catch (err) {
assert.equal(err.response.status, 422)
assert.include(err.response.data, "Property 'type' must be a string!")
}
})
it('should be able to update other user when admin', async () => {
const adminJWT = context.adminJWT
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
headers: {
Authorization: `Bearer ${adminJWT}`
},
data: {
user: {
name: 'This should work'
}
}
}
const result = await axios(options)
// console.log(`result stringified: ${JSON.stringify(result, null, 2)}`)
const userName = result.data.user.name
assert.equal(userName, 'This should work')
})
it('should update user with minimum inputs', async () => {
const _id = context.user._id
const token = context.token
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: { email: 'testToUpdate@test.com' }
}
}
const result = await axios(options)
const user = result.data.user
// console.log(`user: ${util.inspect(user)}`)
assert.property(user, 'type')
assert.property(user, 'email')
assert.property(user, '_id')
assert.equal(user._id, _id)
assert.notProperty(
user,
'password',
'Password property should not be returned'
)
assert.equal(user.email, 'testToUpdate@test.com')
})
it('should update user with all inputs', async () => {
const _id = context.user._id
const token = context.token
const options = {
method: 'PUT',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
},
data: {
user: {
email: 'testToUpdate@test.com',
name: 'my name',
username: 'myUsername'
}
}
}
const result = await axios(options)
const user = result.data.user
// console.log(`user: ${util.inspect(user)}`)
assert.property(user, 'type')
assert.property(user, 'email')
assert.property(user, 'name')
assert.property(user, '_id')
assert.equal(user._id, _id)
assert.notProperty(
user,
'password',
'Password property should not be returned'
)
assert.equal(user.name, 'my name')
assert.equal(user.email, 'testToUpdate@test.com')
assert.equal(user.username, 'myUsername')
})
})
describe('DELETE /users/:id', () => {
it('should not delete user if token is invalid', async () => {
try {
const options = {
method: 'DELETE',
url: `${LOCALHOST}/users/1`,
headers: {
Accept: 'application/json',
Authorization: 'Bearer 1'
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should throw 401 if deleting invalid user', async () => {
const { token } = context
try {
const options = {
method: 'DELETE',
url: `${LOCALHOST}/users/1`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
}
}
await axios(options)
assert.equal(true, false, 'Unexpected behavior')
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should not be able to delete other users unless admin', async () => {
try {
const options = {
method: 'DELETE',
url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
headers: {
Authorization: `Bearer ${context.token}`
}
}
await axios(options)
} catch (err) {
assert.equal(err.response.status, 401)
}
})
it('should delete own user', async () => {
const _id = context.user._id
const token = context.token
const options = {
method: 'DELETE',
url: `${LOCALHOST}/users/${_id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`
}
}
const result = await axios(options)
// console.log(`result: ${util.inspect(result.data.success)}`)
assert.equal(result.data.success, true)
})
it('should be able to delete other users when admin', async () => {
const id = context.id2
const adminJWT = context.adminJWT
const options = {
method: 'DELETE',
url: `${LOCALHOST}/users/${id}`,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${adminJWT}`
}
}
const result = await axios(options)
// console.log(`result: ${util.inspect(result.data)}`)
assert.equal(result.data.success, true)
})
})
//
// describe('PUT /users/:id', () => {
// it('should not update user if token is invalid', async () => {
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/1`,
// headers: {
// Accept: 'application/json',
// Authorization: 'Bearer 1'
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should throw 401 if non-admin updating other user', async () => {
// const { token } = context
//
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/1`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should not be able to update user type', async () => {
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${context.user._id.toString()}`,
// headers: {
// Authorization: `Bearer ${context.token}`
// },
// data: {
// user: {
// name: 'new name',
// type: 'test'
// }
// }
// }
// await axios(options)
//
// // console.log(`Users: ${JSON.stringify(result.data, null, 2)}`)
//
// // assert(result.status === 200, 'Status Code 200 expected.')
// // assert(result.data.user.type === 'user', 'Type should be unchanged.')
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(
// err.response.data,
// "Property 'type' can only be changed by Admin user"
// )
// }
// })
//
// it('should not be able to update other user when not admin', async () => {
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
// headers: {
// Authorization: `Bearer ${context.token}`
// },
// data: {
// user: {
// name: 'This should not work'
// }
// }
// }
// await axios(options)
//
// // console.log(`result: ${JSON.stringify(result.data, null, 2)}`)
//
// assert(false, 'Unexpected result')
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should not be able to update if name property is wrong', async () => {
// try {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// email: 'testToUpdate@test.com',
// name: {}
// }
// }
// }
// await axios(options)
// } catch (error) {
// assert.equal(error.response.status, 422)
// assert.include(error.response.data, "Property 'name' must be a string!")
// }
// })
// it('should not be able to update if password property is not string', async () => {
// const { token } = context
// const _id = context.user._id
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// password: 1234
// }
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(
// err.response.data,
// "Property 'password' must be a string!"
// )
// }
// })
// it('should not be able to update if project property is not array', async () => {
// const { token } = context
// const _id = context.user._id
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// projects: 'projects'
// }
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(
// err.response.data,
// "Property 'projects' must be a Array!"
// )
// }
// })
// it('should not be able to update if email is not string', async () => {
// const { token } = context
// const _id = context.user._id
// try {
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// email: 1234
// }
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(err.response.data, "Property 'email' must be a string!")
// }
// })
// it('should not be able to update if email is wrong format', async () => {
// try {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// email: 'badEmailFormat'
// }
// }
// }
// await axios(options)
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(
// err.response.data,
// "Property 'email' must be email format!"
// )
// }
// })
// it('should not be able to update type property if is not string', async () => {
// try {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// type: 1
// }
// }
// }
// await axios(options)
// } catch (err) {
// assert.equal(err.response.status, 422)
// assert.include(err.response.data, "Property 'type' must be a string!")
// }
// })
//
// it('should be able to update other user when admin', async () => {
// const adminJWT = context.adminJWT
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
// headers: {
// Authorization: `Bearer ${adminJWT}`
// },
// data: {
// user: {
// name: 'This should work'
// }
// }
// }
// const result = await axios(options)
// // console.log(`result stringified: ${JSON.stringify(result, null, 2)}`)
//
// const userName = result.data.user.name
// assert.equal(userName, 'This should work')
// })
// it('should update user with minimum inputs', async () => {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: { email: 'testToUpdate@test.com' }
// }
// }
//
// const result = await axios(options)
// const user = result.data.user
// // console.log(`user: ${util.inspect(user)}`)
//
// assert.property(user, 'type')
// assert.property(user, 'email')
//
// assert.property(user, '_id')
// assert.equal(user._id, _id)
//
// assert.notProperty(
// user,
// 'password',
// 'Password property should not be returned'
// )
// assert.equal(user.email, 'testToUpdate@test.com')
// })
//
// it('should update user with all inputs', async () => {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'PUT',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// },
// data: {
// user: {
// email: 'testToUpdate@test.com',
// name: 'my name',
// username: 'myUsername'
// }
// }
// }
// const result = await axios(options)
//
// const user = result.data.user
// // console.log(`user: ${util.inspect(user)}`)
//
// assert.property(user, 'type')
// assert.property(user, 'email')
// assert.property(user, 'name')
//
// assert.property(user, '_id')
// assert.equal(user._id, _id)
// assert.notProperty(
// user,
// 'password',
// 'Password property should not be returned'
// )
// assert.equal(user.name, 'my name')
// assert.equal(user.email, 'testToUpdate@test.com')
// assert.equal(user.username, 'myUsername')
// })
// })
//
// describe('DELETE /users/:id', () => {
// it('should not delete user if token is invalid', async () => {
// try {
// const options = {
// method: 'DELETE',
// url: `${LOCALHOST}/users/1`,
// headers: {
// Accept: 'application/json',
// Authorization: 'Bearer 1'
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should throw 401 if deleting invalid user', async () => {
// const { token } = context
//
// try {
// const options = {
// method: 'DELETE',
// url: `${LOCALHOST}/users/1`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// }
// }
// await axios(options)
//
// assert.equal(true, false, 'Unexpected behavior')
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should not be able to delete other users unless admin', async () => {
// try {
// const options = {
// method: 'DELETE',
// url: `${LOCALHOST}/users/${context.user2._id.toString()}`,
// headers: {
// Authorization: `Bearer ${context.token}`
// }
// }
// await axios(options)
// } catch (err) {
// assert.equal(err.response.status, 401)
// }
// })
//
// it('should delete own user', async () => {
// const _id = context.user._id
// const token = context.token
//
// const options = {
// method: 'DELETE',
// url: `${LOCALHOST}/users/${_id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${token}`
// }
// }
// const result = await axios(options)
// // console.log(`result: ${util.inspect(result.data.success)}`)
//
// assert.equal(result.data.success, true)
// })
//
// it('should be able to delete other users when admin', async () => {
// const id = context.id2
// const adminJWT = context.adminJWT
//
// const options = {
// method: 'DELETE',
// url: `${LOCALHOST}/users/${id}`,
// headers: {
// Accept: 'application/json',
// Authorization: `Bearer ${adminJWT}`
// }
// }
// const result = await axios(options)
// // console.log(`result: ${util.inspect(result.data)}`)
//
// assert.equal(result.data.success, true)
// })
// })
})
@@ -9,6 +9,7 @@ const sinon = require('sinon')
// Local support libraries
const config = require('../../../config')
const testUtils = require('../../utils/test-utils')
// Unit under test (uut)
const UserLib = require('../../../src/lib/users')
@@ -26,6 +27,9 @@ describe('#users', () => {
useUnifiedTopology: true,
useNewUrlParser: true
})
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
})
beforeEach(() => {
+1 -1
View File
@@ -4,6 +4,6 @@ The tests in this directory are unit tests of REST API. These tests are not
concerned with the business logic behind the endpoints. They are only concerned
with the handling of the REST API endpoint. These tests answer questions like:
- Is the endpoint responding properly to network errors?
- Is the endpoint responding properly when the business logic throws an error?
- When returning an error, is it returning the proper HTTP response?
- When returning success, is it returning the correct payload?
+44 -9
View File
@@ -1,16 +1,15 @@
// const testUtils = require('../../utils/test-utils')
/*
Unit tests for the REST API handler for the /users endpoints.
*/
// Public npm libraries
const assert = require('chai').assert
const config = require('../../../config')
// const axios = require('axios').default
const sinon = require('sinon')
const mongoose = require('mongoose')
const util = require('util')
util.inspect.defaultOptions = { depth: 1 }
// const LOCALHOST = `http://localhost:${config.port}`
// const context = {}
// Local support libraries
const config = require('../../../config')
const testUtils = require('../../utils/test-utils')
const UserController = require('../../../src/modules/users/controller')
let uut
@@ -29,6 +28,9 @@ describe('Users', () => {
useNewUrlParser: true
})
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
// Create a second test user.
@@ -70,6 +72,39 @@ describe('Users', () => {
mongoose.connection.close()
})
describe('#POST /users', () => {
it('should return 422 status on biz logic error', async () => {
try {
await uut.createUser(ctx)
assert.fail('Unexpected result')
} catch (err) {
// console.log(err)
assert.equal(err.status, 422)
assert.include(err.message, 'Cannot read property')
}
})
it('should return 200 status on success', async () => {
ctx.request.body = {
user: {
email: 'test02@test.com',
password: 'test',
name: 'test02'
}
}
await uut.createUser(ctx)
// Assert the expected HTTP response
assert.equal(ctx.status, 200)
// Assert that expected properties exist in the returned data.
assert.property(ctx.response.body, 'user')
assert.property(ctx.response.body, 'token')
})
})
describe('GET /users', () => {
it('should return 422 status on arbitrary biz logic error', async () => {
try {
+42 -7
View File
@@ -1,7 +1,15 @@
/*
Utility functions used to prepare the environment for tests.
*/
// Public NPM libraries
const mongoose = require('mongoose')
const config = require('../../config')
const axios = require('axios').default
// Local libraries
const config = require('../../config')
const User = require('../../src/models/users')
const LOCALHOST = `http://localhost:${config.port}`
// Remove all collections from the DB.
@@ -17,6 +25,24 @@ async function cleanDb () {
}
}
// Delete all users in the database. This ensures there is no previous state
// to confuse tests.
async function deleteAllUsers () {
try {
// Get all the users in the DB.
const users = await User.find({}, '-password')
// console.log(`users: ${JSON.stringify(users, null, 2)}`)
// Delete each user.
for (let i = 0; i < users.length; i++) {
const thisUser = users[i]
await thisUser.remove()
}
} catch (err) {
console.error('Error in test-utils.js/deleteAllUsers()')
}
}
// This function is used to create new users.
// userObj = {
// username,
@@ -30,7 +56,8 @@ async function createUser (userObj) {
data: {
user: {
email: userObj.email,
password: userObj.password
password: userObj.password,
name: userObj.name
}
}
}
@@ -44,7 +71,9 @@ async function createUser (userObj) {
return retObj
} catch (err) {
console.log('Error in utils.js/createUser(): ' + JSON.stringify(err, null, 2))
console.log(
'Error in utils.js/createUser(): ' + JSON.stringify(err, null, 2)
)
throw err
}
}
@@ -72,7 +101,9 @@ async function loginTestUser () {
return retObj
} catch (err) {
console.log('Error authenticating test user: ' + JSON.stringify(err, null, 2))
console.log(
'Error authenticating test user: ' + JSON.stringify(err, null, 2)
)
throw err
}
}
@@ -88,7 +119,8 @@ async function loginAdminUser () {
url: `${LOCALHOST}/auth`,
data: {
email: adminUserData.email,
password: adminUserData.password
password: adminUserData.password,
name: 'admin'
}
}
@@ -104,7 +136,9 @@ async function loginAdminUser () {
return retObj
} catch (err) {
console.log('Error authenticating test admin user: ' + JSON.stringify(err, null, 2))
console.log(
'Error authenticating test admin user: ' + JSON.stringify(err, null, 2)
)
throw err
}
}
@@ -131,5 +165,6 @@ module.exports = {
createUser,
loginTestUser,
loginAdminUser,
getAdminJWT
getAdminJWT,
deleteAllUsers
}