Skip to content

Commit

Permalink
#167730746 Profile Settings (#31)
Browse files Browse the repository at this point in the history
* feature(profile-setting):implement user controller, services, route to fetch User from database
[Start #167730746]

* feature(profile-setting):Users can update profile
[Start #167730746]

* feature(profile-setting):Return all users from db
[Start #167730746]

* feature(profile-setting):add more columns to users table
[Start #167730746]

* feature(profile-setting):write unit test for successful update
[Start #167730746]

* feature(profile-setting):add more test
[Start #167730746]

* feature(profile-setting):change files name
[Start #167730746]

* feature(profile-setting): refactor user controller and model spellings
[Start #167730746]

* feature(profile-setting): generate token for user
[Start #167730746]

* feature(profile-setting): verify token
[Start #167730746]

* feature(profile-setting): remove email from token
[Start #167730746]

* feature(profile-setting): validate user profile fields
[Start #167730746]

* chore(database-signup):create signup database
[Start #167730738]

* chore(user-controller-&-userservice):implement user controller and user service
[Fix #167730738]

* feature(profile-setting): test functionality
[Start #167730746]

* chore(Complete-signup):finish signup for user
[Complete #167730738]

* chore(authorization-&-jwtVerify):add middleware to handle proctected route
[Fix #167730738]

* feature(profile-setting): test functionality
[Start #167730746]

* chore(rename-table-field):rename table field
[Fix #167730738]

* chore(test-signup-user):add test  to signup user feature
[Fix #167730738]

* feature(profile-setting): validate user profile
[Start #167730746]

* chore(test-coverage):add more test coverage
[Fix #167730738]

* feature(profile-setting): document feature
[Start #167730746]

* feature(profile-setting): write more test functionality
[Start #167730746]

* chore(92%-test-coverage):add more test to raise coverage
[Fix #167730738]

* chore(complete):complete ticket
[Fix #167730738]

* feature(profile-setting):validate user profile
[Start #167730746]

* feature(profile-setting): conflicts resolved
[Start #167730746]

* feature(profile-setting): conflicts resolved
[Start #167730746]

* feature(profile-setting): conflicts resolved
[Start #167730746]

* chore(update-env-example):edit env values
[Fix #167730738]

* chore(peer-review-implemented):implement peer review
[Fix #167730738]

* chore(peer-review):implement peer review feedback
[Fix #167730738]

* chore(peer-review):implement peer review feedback
[Fix #167730738]

* chore(peer-review):implement peer review feedback
[Fix #167730738]

* chore(peer-review):implement peer review feedback
[Fix #167730738]

* feature(profile-setting):return token to the response body on GET request
[Start #167730746]

* chore(test):add test framework
[Fix #167730738]

* chore(test):edit test
Fix

* chore(test):rename error message
[Fix #167730738]

* chore(correct-hashpassword):correct compare haspassword
[Fix #167730738]

* feature(profile-setting): change role to roleId on users table
[Start #167730746]

* feature(profile-setting): fix mock test roleId field
  [Start #167730746]

* chore(peer-review):implement review feedback
[Fix #167730738]

* feature(profile-setting):add username and change the base url
[Start #167730746]

* chore(test):edit test file
[Fix #167730738]

* feature(profile-setting):seperate test file
[Start #167730746]

* feature(profile-setting):seperate test file
[Start #167730746]

* feature(profile-setting):seperate test file
[Start #167730746]

* feature(profile-setting):create and clear database for test
[Start #167730746]

* feature(profile-setting):create and clear database for test
[Start #167730746]

* chore(fix-conflict):fix conflict
[Fix #167730738]

* chore(ordered-seeders-folder):rearrange the order of seeder folder
[Fix #167730738]

* chore(add):add DevNote to protect a route from an unsigned User
[Fix #167730738]

* chore(troubleshoot-travis-1):troubleshoot travis
[Fix #167730738]

* chore(troubleshoot-travis-2):troubleshoot travis
[Fix #167730738]

* chore(troubleshoot-travis-2):troubleshoot travis
[Fix #167730738]

* chore(troubleshoot-travis-2):troubleshoot travis
[Fix #167730738]

* feature(profile-setting): remove pretest script
[Start #167730746]

* feature(profile-setting):change model name to small cap
[Start #167730746]

* chore(troubleshoot-travis-2):troubleshoot travis
[Fix #167730738]

* modify package.json

* fix(heroku)rename Role.js to role.js

* fix(travis): rename User.js to user.js

* change destroy to sync

* fix(heroku): add babel as dependency

* fix(heroku): add babel/core to dependencies

* console database url

* add babel modules as dependencies

* add babel modules as dependencies

* update production database uri

* update production database uri

* console db variables

* remove console statements

* add postbuild script

* fix(heroku): update heroku post-build script

* fix(heroku): remove seeding from post-build script

* chore(postbuild-script):add postbuild script
[Fix #167730738]

* chore(postbuild-script):add postbuild script
[Fix #167730738]

* chore(postbuild-script):add postbuild script
[Fix #167730738]

* chore(postbuild-script):rename model folder file
[Fix #167730738]

* chore(postbuild-script):rename model folder file
[Fix #167730738]

* chore(postbuild-script):rename model folder file
[Fix #167730738]

* chore(resolve-conflict):resolve conflict
[Fix #167730738]

* chore(resolve-conflict):resolve conflict
[Fix #167730738]

* chore(descriptive-error-message):add descriptive for multi-scenaro error
[Fix #167730738]

* chore(TTL-review):implement TTL review and consolidate mail package
[Fix #167730738]

* chore(TTL-review):implement TTL review and consolidate mail package
[Fix #167730738]

* chore(TTL-review):implement TTL review and consolidate mail package
[Fix #167730738]

* chore(build-fix):Fixtravis build failure
[Fix #167730738]

* chore(fix-travis):fix travis build fail
[Fix #167730738]

* chore(fix-trailing-space-error):fix trailing spaces error
[Fix #167730738]

* chore(fix-trailing-space-error):fix trailing spaces error
[Fix #167730738]

* chore(fix-trailing-space-error):fix trailing spaces error
[Fix #167730738]

* chore(reset-nodemailer):reset nodemailer
[Fix #167730738]

* chore(reset-nodemailer):reset nodemailer
[Fix #167730738]

* feature(profile-setting):package.json
[Start #167730746]

* chore(services/mail):add services mail
[Fix #167730738]

* chore(services/mail):add services mail
[Fix #167730738]

* chore(node_tls):edit settings
[Fix #167730738]

* chore(nodemailer-settings):settings
[Fix #167730738]

* chore(private-email-amazeninterieurs):add private mail account
[Fix #167730738]

* chore(package.json):add package.json heroku script
[Fix #167730738]

* feature(profile-setting):refactor code and seperate files
[Start #167730746]

* chore(userProfile-settings):write test for user profile settings
[Fix #167730746]

* ch:(profile-settings): fix test bug
rearrange logic for checking user profile
[Start #167730746]

* ch(profile-settings):get token from user signup route
[Finish #167730746]

* ch(profile-settings):fix test bug
[Finish #167730746]

* ft(profile-settings):get user id from the token
[Finish #167730746]

* ch(profile-settings):remove console statement
[Finish #167730746]

* ft(profile-settings):validate gender, phoneNumber
[Finish #167730746]
  • Loading branch information
dewaleolaoye authored and rovilay committed Sep 16, 2019
1 parent 5059f51 commit de10611
Show file tree
Hide file tree
Showing 20 changed files with 529 additions and 170 deletions.
5 changes: 0 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
NODE_ENV=test
SALT= random numbers
TOKENEXPIRY=somenumber
DB_USERNAME=database username
Expand All @@ -18,13 +17,9 @@ YOUR_EMAIL="" (description: email to create test account and receive reset email
SOME_PASSWORD="" (description: password to create a test account, must include no less than 4 characters)
SENDGRID_API_KEY="" (description: sendgrid api key with permission to send mail)
DATABASE_URL="postgres://postgres@localhost:5432/db_name"
DATABASE_URL_TEST="postgres://postgres@localhost:5432/db_name_test"
JWT_SECRET="secret-value"
SECRET="random-charaters"
SECRET_KEY_SIGN_UP=some-secret-value
JWT_SECRET=secret variable to sign and decode tokens
SECRET_KEY_SIGN_UP = choose any random character
EMAIL_VERIFY_TOKEN_SECRET_KEY = choose any random character
TOKENEXPIRY=18000
CLIENT_URL="https://firestar_backend.herokuapp.com"
YOUR_EMAIL="" (description: email to create test account and receive reset email link, must be able to access the email)
84 changes: 55 additions & 29 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,35 +1,61 @@
{
"root": true,
"extends": "airbnb-base",
"env": {
"node": true,
"es6": true,
"mocha": true
},
"rules": {
"one-var": 0,
"one-var-declaration-per-line": 0,
"new-cap": 0,
"no-useless-catch":0,
"consistent-return": 0,
"no-param-reassign": 0,
"comma-dangle": 0,
"indent": ["error", 2],
"curly": ["error", "multi-line"],
"import/no-unresolved": [2, { "commonjs": true }],
"no-shadow": ["error", { "allow": ["req", "res", "err"] }],
"valid-jsdoc": ["error", {
"extends": "airbnb-base",
"env": {
"node": true,
"es6": true,
"mocha": true
},
"rules": {
"one-var": 0,
"one-var-declaration-per-line": 0,
"new-cap": 0,
"no-useless-catch": 0,
"consistent-return": 0,
"no-param-reassign": 0,
"comma-dangle": 0,
"indent": [
"error",
2
],
"curly": [
"error",
"multi-line"
],
"import/no-unresolved": [
2,
{
"commonjs": true
}
],
"no-shadow": [
"error",
{
"allow": [
"req",
"res",
"err"
]
}
],
"valid-jsdoc": [
"error",
{
"requireReturn": true,
"requireReturnType": true,
"requireParamDescription": false,
"requireReturnDescription": true
}],
"require-jsdoc": ["error", {
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
"ClassDeclaration": true
}
}]
}
}
}
],
"require-jsdoc": [
"error",
{
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
"ClassDeclaration": true
}
}
]
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"lint": "eslint \"**/*.js\" --ignore-pattern node_modules/ --fix",
"clean": "rm -rf ./dist && mkdir dist",
"build": "npm run clean && babel ./src -d dist",
"heroku-postbuild": "npm run build && npm run migrate:prod",
"heroku-postbuild": "npm run build && npm run undo:prod && npm run migrate:prod",
"start": "node dist/index.js",
"start:dev": "cross-env NODE_ENV=development nodemon --exec babel-node -- src/index.js",
"migrate:dev": "sequelize db:migrate",
Expand All @@ -37,6 +37,7 @@
"bcrypt": "^3.0.6",
"bcryptjs": "^2.4.3",
"body-parser": "^1.18.3",
"chai-http": "^4.3.0",
"core-js": "^3.2.1",
"cors": "^2.8.4",
"cross-env": "^5.2.0",
Expand Down Expand Up @@ -79,7 +80,7 @@
"mocha-lcov-reporter": "^1.3.0",
"nodemon": "^1.19.1",
"nyc": "^14.1.1",
"sinon": "^7.4.1",
"sinon": "^7.4.2",
"sinon-chai": "^3.3.0"
}
}
1 change: 1 addition & 0 deletions src/__mocks__/emailVerification.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import './validations/resetPassword';
import './routes/users/emailverification';
import './routes/users/signup';
import './routes/users/userRole';
import './routes/users/userProfile';
import './routes/users/login';
63 changes: 5 additions & 58 deletions src/__tests__/routes/users/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,64 +361,11 @@ describe('SIGNUP ROUTE', () => {
it('should say proctected route when token is not present', async () => {
const response = await request.get('/api/v1/users/myaccount')
.set('Authorization', tokenEmail);
expect(response.status).to.equal(401);
expect(response.status).to.equal(400);
expect(response.body).to.be.a('object');
}).timeout(0);
});

describe('STUBS FOR AUTH MIDDLEWARE', () => {
it('reproduce server response when token is not valid /JWTVERIFY', async () => {
const req = {
token: tokenEmail,
};
const res = {
status() {},
json() {},
};

sinon.stub(res, 'status').returnsThis();
sinon.stub(req, 'token').throws();

await jwtVerify(req, res);

expect(res.status).to.have.been.calledWith(401);
});

it('Go to the next middleware when no error in JWTVERIFY', async () => {
const req = {
token: `bearer ${token}`,
};
const res = {
status() {},
json() {},
};

const next = () => 2;

sinon.stub(res, 'status').returnsThis();
sinon.stub(req, 'token').throws();

await jwtVerify(req, res, next);
});


it('reproduce server response when token is not available in Header as Authorization', async () => {
const req = {
header() {}
};
const res = {
status() {},
json() {},
};

sinon.stub(res, 'status').returnsThis();

await authorization(req, res);

expect(res.status).to.have.been.calledWith(401);
});
});

describe('STUBS FOR USERCONTROLLER', () => {
it('reproduce server response to when user exist already in database', async () => {
const req = {
Expand All @@ -431,8 +378,8 @@ describe('SIGNUP ROUTE', () => {
tokenEmail
};
const res = {
status() {},
json() {},
status() { },
json() { },
};

sinon.stub(res, 'status').returnsThis();
Expand All @@ -453,8 +400,8 @@ describe('SIGNUP ROUTE', () => {
tokenEmail
};
const res = {
status() {},
json() {},
status() { },
json() { },
};

sinon.stub(res, 'status').returnsThis();
Expand Down
121 changes: 121 additions & 0 deletions src/__tests__/routes/users/userProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import chai from 'chai';
import chaiHttp from 'chai-http';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import app from '../../../index';

import db from '../../../models';
import { roles } from '../../../__mocks__/userRoles';
import { invalidUserToken } from '../../../__mocks__/emailVerification'

chai.use(chaiHttp);
chai.use(sinonChai);

const { expect } = chai;

let request;
let token;

describe('USER PROFILE', () => {
before(async () => {
request = chai.request(app).keepOpen();
const {
superAdmin, travelAdmin, travelTeamMember, manager, requester
} = roles;
await db.roles.sync({ force: true });
await db.users.sync({ force: true });
await db.logins.sync({ force: true });
await db.roles.bulkCreate([superAdmin, travelAdmin, travelTeamMember, manager, requester]);
});

afterEach(async () => {
sinon.restore();
});
after(async () => {
await db.logins.destroy({ where: {} });
await db.users.destroy({ where: {} });
await db.roles.destroy({ where: {} });
});

describe('SIGN UP USER FIRST', () => {
it('should sign up user first to get user credentials', async () => {
const body = {
user: {
email: 'akps.i@yahoo.com',
firstName: 'Aniefiok',
lastName: 'Akpan',
password: 'ADsd23$$'
}
};
const response = await request.post(`/api/v1/users/auth/register`).send(body.user);
token = response.body.data.token;

expect(response.status).to.equal(201);
expect(response.body).to.be.a('object');
}).timeout(0)
})

describe('GET USER PROFILE', () => {
it('should get user profile with a status of 200', async () => {
const tokenHeader = `Bearer ${token}`
const response = await request.get(`/api/v1/users/profile`)
.set('Authorization', tokenHeader)
expect(response.status).to.equal(200);
expect(response.body.status).to.equal('success');
expect(response.body.message).to.equal('Succesfully found user');
}).timeout(0)
});

describe('GET USER PROFILE', () => {
it('should throw user not found error', async () => {
const tokenHeader = `Bearer ${invalidUserToken}`
const response = await request.get(`/api/v1/users/profile`)
.set('Authorization', tokenHeader)
expect(response.status).to.equal(401);
expect(response.body.status).to.equal('error');
expect(response.body.message).to.equal('User not found');
}).timeout(0)
});

describe('PATCH USER PROFILE', () => {
it('should update user profile', async () => {
const body = {
firstName: 'Adewale',
lastName: 'Olaoye',
department: 'Mathematics'
};
const tokenHeader = `Bearer ${token}`
const response = await request.patch(`/api/v1/users/profile`).send(body)
.set('Authorization', tokenHeader)
expect(response.status).to.equal(201);
expect(response.body.status).to.equal('success');
expect(response.body.message).to.equal('You ve successfully updated your profile');
}).timeout(0)
});

describe('PATCH USER PROFILE', () => {
it('should validate user details', async () => {
const body = {
firstName: 'a',
lastName: 'Olaoye'
};
const tokenHeader = `Bearer ${token}`
const response = await request.patch(`/api/v1/users/profile`).send(body)
.set('Authorization', tokenHeader)
expect(response.status).to.equal(400);
expect(response.body.status).to.equal('error');
expect(response.body.message[0]).to.equal('firstName length must be at least 2 characters long');
}).timeout(0)
});

describe('PATCH USER PROFILE', () => {
it('should throw user not found error', async () => {
const tokenHeader = `Bearer ${invalidUserToken}`
const response = await request.patch(`/api/v1/users/profile`)
.set('Authorization', tokenHeader)
expect(response.status).to.equal(401);
expect(response.body.status).to.equal('error');
expect(response.body.message).to.equal('User not found');
}).timeout(0)
});
});
2 changes: 1 addition & 1 deletion src/controllers/emailController.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class emailVerificationController {
data: {
token: emailToken,
message:
'Message successfully sent, please check your email'
'Message successfully sent, please check your email'
}
});
}
Expand Down
Loading

0 comments on commit de10611

Please sign in to comment.