Skip to content

Commit

Permalink
Implement mentor availability endpoint (#64)
Browse files Browse the repository at this point in the history
Co-authored-by: Yoshitha Rathnayake <[email protected]>
  • Loading branch information
Shrenik0321 and YoshithaRathnayake authored Sep 23, 2023
1 parent 538f1fb commit c95e3bc
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 3 deletions.
22 changes: 20 additions & 2 deletions src/controllers/mentor.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Request, Response } from 'express'
import { createMentor } from '../services/mentor.service'
import { createMentor, updateAvailability } from '../services/mentor.service'
import type Profile from '../entities/profile.entity'

export const mentorApplicationHandler = async (
Expand All @@ -9,7 +9,6 @@ export const mentorApplicationHandler = async (
try {
const user = req.user as Profile
const { application, categoryId } = req.body

const { mentor, statusCode, message } = await createMentor(
user,
application,
Expand All @@ -26,3 +25,22 @@ export const mentorApplicationHandler = async (
}
}
}

export const mentorAvailabilityHandler = async (
req: Request,
res: Response
): Promise<void> => {
try {
const user = req.user as Profile
const { availability } = req.body
const result = await updateAvailability(user, availability)
res.status(result.statusCode).json(result.updatedMentorApplication)
} catch (err) {
if (err instanceof Error) {
console.error('Error executing query', err)
res
.status(500)
.json({ error: 'Internal server error', message: err.message })
}
}
}
82 changes: 82 additions & 0 deletions src/routes/admin/admin.route.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { startServer } from '../../app'
import type { Express } from 'express'
import supertest from 'supertest'
import Profile from '../../entities/profile.entity'
import { ProfileTypes } from '../../enums'
import { dataSource } from '../../configs/dbConfig'
import bcrypt from 'bcrypt'
import { mockAdmin, mockUser } from '../../../mocks'

const port = Math.floor(Math.random() * (9999 - 3000 + 1)) + 3000
let server: Express
let agent: supertest.SuperAgentTest
let adminAgent: supertest.SuperAgentTest

describe('Get all users route', () => {
beforeAll(async () => {
server = await startServer(port)
agent = supertest.agent(server)
adminAgent = supertest.agent(server)

const defaultUser = {
...mockUser
}

await supertest(server)
.post('/api/auth/register')
.send(defaultUser)
.expect(201)

await agent.post('/api/auth/login').send(defaultUser).expect(200)

const adminUser = {
...mockAdmin
}

const profileRepository = dataSource.getRepository(Profile)

const hashedPassword = await bcrypt.hash(adminUser.password, 10)
const newProfile = profileRepository.create({
primary_email: adminUser.email,
password: hashedPassword,
contact_email: '',
first_name: '',
last_name: '',
image_url: '',
linkedin_url: '',
type: ProfileTypes.ADMIN
})

await profileRepository.save(newProfile)

await adminAgent.post('/api/auth/login').send(adminUser).expect(200)
}, 5000)

it('should return a 401 when a valid access token is not provided', async () => {
await supertest(server).get('/api/admin/users').expect(401)
})

it('should return a 403 if user is not admin', async () => {
await agent.get('/api/admin/users').expect(403)
})

it('should return a 200 with all users if user is admin', async () => {
const response = await adminAgent.get('/api/admin/users').expect(200)

const userProfiles = response.body.profiles

userProfiles.forEach((userProfile: Partial<Profile>) => {
expect(userProfile).toHaveProperty('created_at')
expect(userProfile).toHaveProperty('updated_at')
expect(userProfile).toHaveProperty('primary_email')
expect(userProfile).toHaveProperty('contact_email')
expect(userProfile).toHaveProperty('first_name')
expect(userProfile).toHaveProperty('last_name')
expect(userProfile).toHaveProperty('image_url')
expect(userProfile).toHaveProperty('linkedin_url')
expect(userProfile).toHaveProperty('type')
expect(userProfile).toHaveProperty('uuid')
expect(userProfile).not.toHaveProperty('password')
})
})
})
14 changes: 14 additions & 0 deletions src/routes/mentor/mentor.route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ describe('Mentor application', () => {
await supertest(server).post('/api/mentors').send({}).expect(401)
})

describe('Update Mentor Availability', () => {
it.each([true, false])(
'should update mentor availability and return a 201 with the updated availability',
async (availability) => {
const response = await agent
.put('/api/mentors/me/availability')
.send({ availability })
.expect(200)

expect(response.body).toHaveProperty('availability', availability)
}
)
})

afterAll(async () => {
await dataSource.destroy()
})
Expand Down
6 changes: 5 additions & 1 deletion src/routes/mentor/mentor.route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import express from 'express'
import { requireAuth } from './../../controllers/auth.controller'
import { mentorApplicationHandler } from './../../controllers/mentor.controller'
import {
mentorApplicationHandler,
mentorAvailabilityHandler
} from './../../controllers/mentor.controller'

const mentorRouter = express.Router()

mentorRouter.post('/', requireAuth, mentorApplicationHandler)
mentorRouter.put('/me/availability', requireAuth, mentorAvailabilityHandler)

export default mentorRouter
8 changes: 8 additions & 0 deletions src/services/admin.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { dataSource } from '../configs/dbConfig'
import Profile from '../entities/profile.entity'

export const getAllUsers = async (): Promise<Profile[] | undefined> => {
const profileRepository = dataSource.getRepository(Profile)
const allUsers = await profileRepository.find()
return allUsers
}
30 changes: 30 additions & 0 deletions src/services/mentor.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,33 @@ export const createMentor = async (
throw new Error('Error creating mentor')
}
}

export const updateAvailability = async (
user: Profile,
availability: boolean
): Promise<{ statusCode: number; updatedMentorApplication: Mentor }> => {
try {
const mentorRepository = dataSource.getRepository(Mentor)
const existingMentorApplications = await mentorRepository.find({
where: { profile: { uuid: user.uuid } }
})

const mentorApplication = existingMentorApplications[0]

if (mentorApplication) {
mentorApplication.availability = availability
const updatedMentorApplication = await mentorRepository.save(
mentorApplication
)
return {
statusCode: 200,
updatedMentorApplication
}
} else {
throw new Error('Mentor application not found')
}
} catch (err) {
console.error('Error creating mentor', err)
throw new Error('Error creating mentor')
}
}

0 comments on commit c95e3bc

Please sign in to comment.