mirror of
https://github.com/Permissionless-Software-Foundation/x402-base-facilitator.git
synced 2026-09-21 16:52:01 -07:00
Got npm test working again
This commit is contained in:
+8
-7
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user