Skip to content

Commit

Permalink
Merge pull request #6 from jkarenzi/ft-auth-#2
Browse files Browse the repository at this point in the history
Feat: Implement authentication and Authorization #2
  • Loading branch information
jkarenzi authored Jun 10, 2024
2 parents 30b434c + 0a098d3 commit c1d809f
Show file tree
Hide file tree
Showing 22 changed files with 998 additions and 1,493 deletions.
27 changes: 18 additions & 9 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended"],
"env": {
"node": true,
"es6": true
"es2021": true
},
"rules": {
"no-console": "warn",
"quotes": ["error", "single"]
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"ignorePatterns": ["dist/**/*", "__tests__/*"]
}
"plugins": [
"@typescript-eslint"
],
"rules": {
"quotes": ["error", "single"],
"no-console": ["warn", { "allow": ["warn", "error"] }],
"@typescript-eslint/no-var-requires": "off"
}
}
7 changes: 1 addition & 6 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
**what does this PR do?**


**Description of the task to be completed**


**How can this be manually tested?**


**Swagger documentation screenshot**


**Test screenshot**


**What are the relevant pivotal trackers/story id?**
**What are the relevant pivotal trackers/story id?**
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# TaskMaster API
# TaskMaster API

[![CI for taskMaster Project](https://github.com/jkarenzi/task-master-be/actions/workflows/CI.yaml/badge.svg)](https://github.com/jkarenzi/task-master-be/actions/workflows/CI.yaml)

Expand Down Expand Up @@ -53,4 +53,4 @@ Once the development server is running, you can interact with the API using HTTP

## Authors

- [Manzi Karenzi](https://github.com/jkarenzi)
- [Manzi Karenzi](https://github.com/jkarenzi)
134 changes: 134 additions & 0 deletions __tests__/authController.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
export {};
const request = require('supertest');
const app = require('../src/app');
const bcrypt = require('bcrypt');
const {
signUpSchema,
loginSchema,
} = require('../src/middleware/validators/authSchema');
const jwt = require('jsonwebtoken')
const User = require('../src/models/User');

jest.mock('../src/models/User');
jest.mock('../src/middleware/validators/authSchema');
jest.mock('bcrypt');
jest.mock('jsonwebtoken')

describe('Auth Controller Tests', () => {
const signUpFormData = {
fullName: 'test tester',
email: '[email protected]',
password: 'test123456',
};

const loginFormData = {
email: '[email protected]',
password: 'test123456',
};

const returnedUser = {
_id:'some id',
fullName:'mock user',
email:'[email protected]',
password:'password1234',
createdAt: 'some date',
updatedAt: 'some date'
}

it('should return a 201 if signup is successful', async () => {
signUpSchema.validate.mockReturnValueOnce({ error: null });

User.findOne.mockImplementationOnce(() => Promise.resolve(null));

bcrypt.hash.mockResolvedValueOnce('hashed password');

User.prototype.save.mockResolvedValueOnce(returnedUser);

const response = await request(app).post('/api/auth/signup').send(signUpFormData);
expect(response.status).toBe(201);
expect(User.prototype.save).toHaveBeenCalled();
});

it('should return a 400 if validation fails on signup', async () => {
signUpSchema.validate.mockReturnValueOnce({ error: { details: [{ message: 'Validation failed' }] } });

const response = await request(app).post('/api/auth/signup').send(signUpFormData);
expect(response.status).toBe(400);
expect(response.body.message).toBeDefined();
})

it('should return a 409 if email already exists', async () => {
signUpSchema.validate.mockReturnValueOnce({ error: null });

User.findOne.mockImplementationOnce(() => Promise.resolve({
_id:'some id',
fullName:'mock user',
email:'[email protected]',
password:'password1234',
createdAt: 'some date',
updatedAt: 'some date'
}));

const response = await request(app).post('/api/auth/signup').send(signUpFormData);
expect(response.status).toBe(409);
expect(response.body.message).toBe('Email already in use');
})

it('should return a 500 if an error occurs during signup', async () => {
signUpSchema.validate.mockReturnValueOnce({ error: null });
User.findOne.mockImplementationOnce(() => {throw new Error('DB error')})

const response = await request(app).post('/api/auth/signup').send(signUpFormData);
expect(response.status).toBe(500);
expect(response.body.message).toBe('Internal Server Error');
})

it('should return a 200 if login is successful', async () => {
loginSchema.validate.mockReturnValueOnce({ error: null });
User.findOne.mockImplementationOnce(() => Promise.resolve(returnedUser))

bcrypt.compare.mockResolvedValueOnce(true)

jwt.sign.mockResolvedValueOnce('fake token')

const response = await request(app).post('/api/auth/login').send(loginFormData);
expect(response.status).toBe(200);
expect(response.body.message).toBe('Login successful');
})

it('should return a 400 if validation fails on login', async () => {
loginSchema.validate.mockReturnValueOnce({ error: { details: [{ message: 'Validation failed' }] } });

const response = await request(app).post('/api/auth/login').send(loginFormData);
expect(response.status).toBe(400);
expect(response.body.message).toBeDefined()
})

it('should return a 404 if account if not found during login', async () => {
loginSchema.validate.mockReturnValueOnce({ error: null });
User.findOne.mockImplementationOnce(() => Promise.resolve(null))
const response = await request(app).post('/api/auth/login').send(loginFormData);
expect(response.status).toBe(404);
expect(response.body.message).toBe('Account not found');
})

it('should return a 401 if password provided is incorrect, in login', async () => {
loginSchema.validate.mockReturnValueOnce({ error: null });
User.findOne.mockImplementationOnce(() => Promise.resolve(returnedUser))

bcrypt.compare.mockResolvedValueOnce(false)

const response = await request(app).post('/api/auth/login').send(loginFormData);
expect(response.status).toBe(401);
expect(response.body.message).toBe('Incorrect password');
})

it('should return a 500 if an error occurs during login', async () => {
loginSchema.validate.mockReturnValueOnce({ error: null });
User.findOne.mockImplementationOnce(() => {throw new Error('DB error')})

const response = await request(app).post('/api/auth/login').send(loginFormData);
expect(response.status).toBe(500);
expect(response.body.message).toBe('Internal Server Error');
})
});
19 changes: 5 additions & 14 deletions __tests__/test.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { test } from '../src/controllers/testController';
export {}
const request = require('supertest');
const app = require('../src/app');

const res: any = {};

(res.json = jest.fn((x: Object) => x)),
(res.status = jest.fn((x: number) => res));

const req: any = {
body: {
name: 'test',
},
};

describe('Test', () => {
it('should return 200 successful upon testing route', async () => {
await test(req, res);

expect(res.status).toHaveBeenCalledWith(200);
const response = await request(app).get('/api/test')
expect(response.status).toBe(200);
});
});
Loading

0 comments on commit c1d809f

Please sign in to comment.