From 9580be74f5ce3212a06406b2d0d03ddb5beea1a2 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Date: Wed, 11 Nov 2020 23:24:47 -0400 Subject: [PATCH] feat(users): Increased user controller to 100% test coverage --- src/modules/users/controller.js | 14 +- test/a02-users.spec.js | 392 +++++++++++++++++++++----------- 2 files changed, 269 insertions(+), 137 deletions(-) diff --git a/src/modules/users/controller.js b/src/modules/users/controller.js index a1945a1..3f003a9 100644 --- a/src/modules/users/controller.js +++ b/src/modules/users/controller.js @@ -47,15 +47,14 @@ class UserController { * } */ async createUser (ctx) { - const user = new _this.User(ctx.request.body.user) - + const userObj = ctx.request.body.user try { /* * ERROR HANDLERS * */ // Required property - if (!user.email || typeof user.email !== 'string') { + if (!userObj.email || typeof userObj.email !== 'string') { throw new Error("Property 'email' must be a string!") } @@ -66,14 +65,15 @@ class UserController { // throw new Error("Property 'email' must be email format!") // } - if (!user.password || typeof user.password !== 'string') { + if (!userObj.password || typeof userObj.password !== 'string') { throw new Error("Property 'password' must be a string!") } - if (user.name && typeof user.name !== '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' @@ -158,6 +158,7 @@ class UserController { * * @apiUse TokenError */ + async getUser (ctx, next) { try { const user = await _this.User.findById(ctx.params.id, '-password') @@ -237,7 +238,8 @@ class UserController { if (userObj.email && typeof userObj.email !== 'string') { throw new Error("Property 'email' must be a string!") } - const isEmail = await _this.validateEmail(user.email) + + const isEmail = await _this.validateEmail(userObj.email) if (userObj.email && !isEmail) { throw new Error("Property 'email' must be email format!") } diff --git a/test/a02-users.spec.js b/test/a02-users.spec.js index 84cb249..9479458 100644 --- a/test/a02-users.spec.js +++ b/test/a02-users.spec.js @@ -49,11 +49,11 @@ describe('Users', () => { } } - const result = await axios(options) + await axios(options) - console.log( + /* console.log( `result stringified: ${JSON.stringify(result.data, null, 2)}` - ) + ) */ assert(false, 'Unexpected result') } catch (err) { assert(err.response.status === 422, 'Error code 422 expected.') @@ -127,6 +127,30 @@ describe('Users', () => { ) } }) + it('should reject if name property property is not string', async () => { + try { + const options = { + method: 'POST', + url: `${LOCALHOST}/users`, + data: { + user: { + email: 'test322@test.com', + password: 'supersecretpassword', + name: 1234 + } + } + } + await axios(options) + + assert(false, 'Unexpected result') + } catch (err) { + assert.equal(err.response.status, 422) + assert.include( + err.response.data, + "Property 'name' must be a string" + ) + } + }) it("should signup of type 'user' by default", async () => { const options = { @@ -362,6 +386,240 @@ describe('Users', () => { } }) + 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 @@ -435,134 +693,6 @@ describe('Users', () => { assert.equal(user.email, 'testToUpdate@test.com') assert.equal(user.username, 'myUsername') }) - - 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' - } - } - } - const result = 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' - } - } - } - const result = 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 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 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 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, 'not a valid Email format') - } - }) }) describe('DELETE /users/:id', () => {