Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
 into SS-1.4
  • Loading branch information
MOHAMMED1MEDHAT committed Sep 21, 2023
2 parents 54f3e7b + ee1072c commit 72ab6b0
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 94 deletions.
31 changes: 5 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@
| Features | Description |
|----------------------------------|------------------------------------------------------------------------------------------------------|
| Authentication and Authorization System | This feature provides users with login and logout functionality to access the system. |
| Managing & Scheduling Live Sessions | |
| Real-Time Matching System | |
| Payment system | |
| Optimized Feed | |
| Scheduling Live Sessions | Empower users to request mentorship sessions and provide the option to either accept or decline them. |
| Real-Time Matching System | A Real-Time matching system that connects the two most pertinent individuals in a live session |
| Optimized Feed | The platform's feed revolves around user-specific data, ensuring that each user receives personalized mentor suggestions and matching experiences |


## Digrams
Expand Down Expand Up @@ -60,14 +59,8 @@ Before using the API, you need to set the variables in Postman depending on your
- {{URL}} with your hostname as value (Eg. http://127.0.0.1:3000 or http://www.example.com)
- {{password}} with your user password as value.
```
For more info check API Documentation on Postman 👉 : [Natours API Documentation](https://documenter.getpostman.com/view/8689170/SVmzvwpY?version=latest).
For more info check API Documentation on Postman 👉 : [Skill-Sync API Documentation](https://documenter.getpostman.com/view/24663115/2s9YC7SWnB).
- Some API End-Points:
- 👉 [Tours List](https://natours-pw5m.onrender.com/api/v1/tours)
- 👉 [Tours State](https://natours-pw5m.onrender.com/api/v1/tours/tour-stats)
- 👉 [Get Top 5 Cheap Tours](https://natours-pw5m.onrender.com/api/v1/tours/top_5_rated)
- 👉 [Get Tours Within Radius](https://natours-pw5m.onrender.com/api/v1/tours/tours-within/200/center/34.098453,-118.096327/unit/mi)
- 👉 [Get Tours Plans In Each Month](https://natours-pw5m.onrender.com/api/v1/tours/monthly-plan/2021)
| General Package | Description |
|--------------------------|--------------------------------------------------|
Expand Down Expand Up @@ -131,22 +124,8 @@ Security Packages | Development Packages
:-------------------------:|:-------------------------:
<img width="500px" src="https://github.com/Skill-Sync/SkillSync-Backend/blob/master/.github/res/imgs/Security%20Packages.png" /> |<img width="500px" src="https://github.com/Skill-Sync/SkillSync-Backend/blob/master/.github/res/imgs/Development%20Packages.png" /> <br> we utilize [ESLint](https://eslint.org/) and [Prettier](https://prettier.io/) for formatting and style.















## CI/CD Pipeline
-
- We have established a continuous deployment pipeline by connecting our two primary branches (develop and master) to Render serverless applications. This setup ensures that we maintain two server instances, the main and the backup, both of which receive a new deployment with each merge into their respective branches..

## Team-Members
#### BackEnd Team consists of:
Expand Down
4 changes: 2 additions & 2 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ const friendsRouter = require('./routes/friend.routes');
const meetingsRouter = require('./routes/meeting.routes');
//--------------------------------//
const app = express();
// if (process.env.NODE_ENV === 'development')
app.use(morgan('dev'));
if (process.env.NODE_ENV === 'development') app.use(morgan('dev'));
else app.use(morgan(''));

app.use(cors());
app.options('*', cors());
Expand Down
2 changes: 1 addition & 1 deletion src/models/friendship.model.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const mongoose = require('mongoose');
//-------------------Schema----------------//
//-------------------Schema----------------//
// Please note that we intentionally did not create a 'friends' model with a user and an array of his friends. This decision aligns with our app's logic, where becoming friends with someone is based on mutual consent without requiring any requests or approvals. we know this approach may not be the best for scalability, but it is just a way to go for now."

const friendshipsSchema = new mongoose.Schema({
Expand Down
Empty file removed src/routes/admin.test.js
Empty file.
129 changes: 64 additions & 65 deletions src/routes/auth.test.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,82 @@
const request = require('supertest');
const app = require('../app');

const { mongoConnect, mongoDisconnect } = require('../utils/mongoDB');
//--------------------------------//
describe('Authentication and Authorization endpoints testing', () => {
beforeAll(async () => {
await mongoConnect();
});
beforeAll(async () => {
await mongoConnect();
});

afterAll(async () => {
await mongoDisconnect();
});
afterAll(async () => {
await mongoDisconnect();
});

describe('Authentication', () => {
const UserSignUpData = {};
const InvalidUserSignUpData = {};
describe('Authentication', () => {
const UserSignUpData = {};
const InvalidUserSignUpData = {};

const MentorSignUpData = {};
const InvalidMentorSignUpData = {};
const MentorSignUpData = {};
const InvalidMentorSignUpData = {};

const UserLoginData = {};
const InvalidUserLoginData = {};
const UserLoginData = {};
const InvalidUserLoginData = {};

describe('Signup endpoints', () => {
test('User signup should respond with 201', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(UserSignUpData)
.expect('Content-Type', /json/)
.expect(201);
expect(response.body.user.role).toBe('user');
});
describe('Signup endpoints', () => {
test('User signup should respond with 201', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(UserSignUpData)
.expect('Content-Type', /json/)
.expect(201);
expect(response.body.user.role).toBe('user');
});

test('Mentor signup should respond with 201', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(MentorSignUpData)
.expect('Content-Type', /json/)
.expect(201);
expect(response.body.user.role).toBe('mentor');
});
test('Mentor signup should respond with 201', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(MentorSignUpData)
.expect('Content-Type', /json/)
.expect(201);
expect(response.body.user.role).toBe('mentor');
});

test('User signup should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(InvalidUserSignUpData)
.expect('Content-Type', /json/)
.expect(400);
});
test('User signup should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(InvalidUserSignUpData)
.expect('Content-Type', /json/)
.expect(400);
});

test('Mentor signup should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(InvalidMentorSignUpData)
.expect('Content-Type', /json/)
.expect(400);
});
});
test('Mentor signup should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/signup')
.send(InvalidMentorSignUpData)
.expect('Content-Type', /json/)
.expect(400);
});
});

describe('Login endpoints', () => {
test('User login should respond with 200', async () => {
const response = await request(app)
.post('/api/v1/authRouter/login')
.send(UserLoginData)
.expect('Content-Type', /json/)
.expect(200);
});
describe('Login endpoints', () => {
test('User login should respond with 200', async () => {
const response = await request(app)
.post('/api/v1/authRouter/login')
.send(UserLoginData)
.expect('Content-Type', /json/)
.expect(200);
});

test('User login should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/login')
.send(InvalidUserLoginData)
.expect('Content-Type', /json/)
.expect(400);
});
test('User login should catch missing required properties', async () => {
const response = await request(app)
.post('/api/v1/authRouter/login')
.send(InvalidUserLoginData)
.expect('Content-Type', /json/)
.expect(400);
});
});
});
});

describe('Authorization', () => {
// Authorization endpoints such as ask for new access token using refresh token will be tested here
});
describe('Authorization', () => {
// Authorization endpoints such as ask for new access token using refresh token will be tested here
});
});
49 changes: 49 additions & 0 deletions src/routes/friend.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const request = require('supertest');
const app = require('../app');
const { mongoConnect, mongoDisconnect } = require('../utils/mongoDB');
//--------------------------------//
const accessToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWNjZXNzIiwiaWQiOiI2NTA0YmRlYWExZjliMTU1NGI5YjAwNjUiLCJ1c2VyVHlwZSI6InVzZXIiLCJpYXQiOjE2OTQ4OTE1NDAsImV4cCI6MTY5NDg5MjQ0MH0.CNrsSxPBCJ3NveCQUyRolfBdbHws3H6suy4SH74lAls`;
const refreshToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoicmVmcmVzaCIsImlkIjoiNjUwNGJkZWFhMWY5YjE1NTRiOWIwMDY1IiwidXNlclR5cGUiOiJ1c2VyIiwicmVmcmVzaFNlc3Npb24iOiI2NTA1ZmUxNGE5MDFjNGQ4YzUwOGFjMWYiLCJpYXQiOjE2OTQ4OTE1NDAsImV4cCI6MTY5NTQ5NjM0MH0.g-PRJ_sv3hjCQqGzFaLpsnzkmVIuOnkzRTYURiqE_3A`;
//--------------------------------//

const mockFriendship = {
status: 'accepted'
};

beforeAll(async () => {
await mongoConnect();
});

afterAll(async () => {
await mongoDisconnect();
});

describe('User Routes', () => {
it('should get a list of user friends', async () => {
const response = await request(app)
.get('/users')
.set('Authorization', `Bearer ${accessToken} ${refreshToken}`);

expect(response.statusCode).toBe(200);
expect(response.body.status).toBe('success');
expect(response.body.friends).toBeDefined();
});

it('should create or edit a friendship', async () => {
const response = await request(app)
.post('/users/6504bdeaa1f9b1554b9b0065')
.set('Authorization', `Bearer ${accessToken} ${refreshToken}`)
.send(mockFriendship);

expect(response.statusCode).toBe(200);
expect(response.body.newFriendship).toBeDefined();
});

it('should delete a friendship', async () => {
const response = await request(app)
.delete('/users/6504bdeaa1f9b1554b9b0065')
.set('Authorization', `Bearer ${accessToken} ${refreshToken}`);

expect(response.statusCode).toBe(204);
});
});
84 changes: 84 additions & 0 deletions src/routes/meeting.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const request = require('supertest');
const app = require('../app'); // Assuming your Express app is in this file
const { mongoConnect, mongoDisconnect } = require('../utils/mongoDB');
//--------------------------------//
const UserAccessToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWNjZXNzIiwiaWQiOiI2NTA0YmRlYWExZjliMTU1NGI5YjAwNjUiLCJ1c2VyVHlwZSI6InVzZXIiLCJpYXQiOjE2OTQ4OTE1NDAsImV4cCI6MTY5NDg5MjQ0MH0.CNrsSxPBCJ3NveCQUyRolfBdbHws3H6suy4SH74lAls`;
const UserRefreshToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoicmVmcmVzaCIsImlkIjoiNjUwNGJkZWFhMWY5YjE1NTRiOWIwMDY1IiwidXNlclR5cGUiOiJ1c2VyIiwicmVmcmVzaFNlc3Npb24iOiI2NTA1ZmUxNGE5MDFjNGQ4YzUwOGFjMWYiLCJpYXQiOjE2OTQ4OTE1NDAsImV4cCI6MTY5NTQ5NjM0MH0.g-PRJ_sv3hjCQqGzFaLpsnzkmVIuOnkzRTYURiqE_3A`;

const mentorAccessToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWNjZXNzIiwiaWQiOiI2NTA0YmRmN2ExZjliMTU1NGI5YjAwODkiLCJ1c2VyVHlwZSI6Im1lbnRvciIsImlhdCI6MTY5NDg5MzUxNiwiZXhwIjoxNjk0ODk0NDE2fQ.hRqd90Y8UqSQrgLeajv5hJJTxD67_WOXKmmi4uHFnGY`;
const mentorRefreshToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoicmVmcmVzaCIsImlkIjoiNjUwNGJkZjdhMWY5YjE1NTRiOWIwMDg5IiwidXNlclR5cGUiOiJtZW50b3IiLCJyZWZyZXNoU2Vzc2lvbiI6IjY1MDYwNWNjNWQ4ZWIwYzllNzI2ODAzNyIsImlhdCI6MTY5NDg5MzUxNiwiZXhwIjoxNjk1NDk4MzE2fQ.LqROYWhiFj1BzmE8s0MtOc5AV1hAJ6tpilJJovZsGCM`;
//--------------------------------//
const testUser = {
_id: 'testUserId',
userType: 'user'
};

const testMeeting = {
_id: '6504e775469e21d5c0bfef66',
mentor: '6504bdf7a1f9b1554b9b0089',
user: '6504bdeaa1f9b1554b9b0065'
};

beforeAll(async () => {
await mongoConnect();
});

afterAll(async () => {
await mongoDisconnect();
});

describe('Express Routes', () => {
it('should get user meetings', async () => {
const response = await request(app)
.get('/meetings')
.set(
'Authorization',
`Bearer ${UserAccessToken} ${UserRefreshToken}`
)
.expect(200);

expect(response.body.status).toBe('success');
expect(response.body.data.length).toBeGreaterThan(0);
});

it('should get a meeting by ID', async () => {
const response = await request(app)
.get(`/meetings/${testMeeting._id}`)
.set(
'Authorization',
`Bearer ${UserAccessToken} ${UserRefreshToken}`
)
.expect(200);

expect(response.body.status).toBe('success');
expect(response.body.data._id).toBe(testMeeting._id);
});

it('should create a new meeting', async () => {
const response = await request(app)
.patch(`/meetings/6504e775469e21d5c0bfef71`)
.set(
'Authorization',
`Bearer ${UserAccessToken} ${UserRefreshToken}`
)
.send({})
.expect(200);

expect(response.body.status).toBe('success');
expect(response.body.data.status).toBe('accepted');
});

it('should update a meeting', async () => {
const response = await request(app)
.post(`/meetings/6504e775469e21d5c0bfef71`)
.set(
'Authorization',
`Bearer ${mentorAccessToken} ${mentorRefreshToken}`
)
.send({ status: 'accepted' })
.expect(200);

expect(response.body.status).toBe('success');
expect(response.body.data.status).toBe('accepted');
});
});
Empty file removed src/routes/mentor.test.js
Empty file.
Loading

0 comments on commit 72ab6b0

Please sign in to comment.