Skip to content

Commit

Permalink
Update question endpoint (#577)
Browse files Browse the repository at this point in the history
* fix conflicts

* fix some comments

* fix some conflicts

* updated and fix comments

* remove logs

* fix test on question
  • Loading branch information
ArturBekhDEV authored Sep 19, 2023
1 parent f79ce53 commit 3094684
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 6 deletions.
12 changes: 11 additions & 1 deletion controllers/question.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@ const createQuestion = async (req, res) => {
res.status(201).json(newQuestion)
}

const updateQuestion = async (req, res) => {
const { id } = req.params
const { id: currentUserId } = req.user
const data = req.body
await questionService.updateQuestion(id, currentUserId, data)

res.status(204).end()
}

module.exports = {
getQuestions,
createQuestion
createQuestion,
updateQuestion
}
60 changes: 58 additions & 2 deletions docs/questions/question.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ paths:
example:
items:
- _id: 64ca5914b57f2442403394a5
title: Is Assembly best programming language?
title: Is Assembly best programming language?
answers:
- text: Yes,
isCorrect: false
Expand Down Expand Up @@ -71,4 +71,60 @@ paths:
example:
status: 401
code: UNAUTHORIZED
message: The requested URL requires user authorization.
message: The requested URL requires user authorization.
patch:
security:
- bearerAuth: []
tags:
- Questions
summary: Update question by id.
description: Updates question by id.
produces:
- application/json
parameters:
- in: params
name: id
required: true
description: id of the question that needs to be updated
type: string
requestBody:
description: Data to update a question
content:
application/json:
schema:
$ref: '#/definitions/questionBody'
example:
title: WebAssembly
responses:
204:
description: No content
401:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/Error'
example:
status: 401
code: UNAUTHORIZED
message: The requested URL requires user authorization.
403:
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/Error'
example:
status: 403
code: FORBIDDEN
message: You do not have permission to perform this action.
404:
description: Not found
content:
application/json:
schema:
$ref: '#/components/Error'
example:
status: 404
code: NOT_FOUND
message: Question with the specified id was not found.
5 changes: 5 additions & 0 deletions routes/question.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
const router = require('express').Router()
const Question = require('~/models/question')

const questionController = require('~/controllers/question')
const asyncWrapper = require('~/middlewares/asyncWrapper')
const isEntityValid = require('~/middlewares/entityValidation')
const { authMiddleware, restrictTo } = require('~/middlewares/auth')

const {
roles: { TUTOR }
} = require('~/consts/auth')

router.use(authMiddleware)
const params = [{ model: Question, idName: 'id' }]

router.get('/', asyncWrapper(questionController.getQuestions))
router.use(restrictTo(TUTOR))
router.post('/', asyncWrapper(questionController.createQuestion))
router.patch('/:id', isEntityValid({ params }), asyncWrapper(questionController.updateQuestion))

module.exports = router
18 changes: 16 additions & 2 deletions services/question.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const Question = require('~/models/question')
const { createForbiddenError } = require('~/utils/errorsHelper')

const questionService = {
getQuestions: async (match, sort, skip = 0, limit = 10) => {
const items = await Question
.find(match)
const items = await Question.find(match)
.collation({ locale: 'en', strength: 1 })
.sort(sort)
.skip(skip)
Expand All @@ -24,6 +24,20 @@ const questionService = {
type,
author
})
},

updateQuestion: async (id, currentUserId, data) => {
const question = await Question.findById(id).exec()

const author = question.author.toString()

if (currentUserId !== author) {
throw createForbiddenError()
}
for (let field in data) {
question[field] = data[field]
}
await question.save()
}
}
module.exports = questionService
41 changes: 40 additions & 1 deletion test/integration/controllers/question.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { expectError } = require('~/test/helpers')
const { UNAUTHORIZED, FORBIDDEN } = require('~/consts/errors')
const testUserAuthentication = require('~/utils/testUserAuth')
const TokenService = require('~/services/token')
const Question = require('~/models/question')
const {
roles: { TUTOR }
} = require('~/consts/auth')
Expand Down Expand Up @@ -36,8 +37,13 @@ const studentUserData = {
lastLoginAs: 'student'
}

const updateData = {
title: 'Here is updated one!',
type: 'multipleChoice'
}

describe('Question controller', () => {
let app, server, accessToken, currentUser, studentAccessToken, testQuestion
let app, server, accessToken, currentUser, studentAccessToken, testQuestion, testQuestionId

beforeAll(async () => {
;({ app, server } = await serverInit())
Expand All @@ -50,6 +56,7 @@ describe('Question controller', () => {
currentUser = TokenService.validateAccessToken(accessToken)

testQuestion = await app.post(endpointUrl).send(testQuestionData).set('Authorization', `Bearer ${accessToken}`)
testQuestionId = testQuestion.body._id
})

afterEach(async () => {
Expand Down Expand Up @@ -110,4 +117,36 @@ describe('Question controller', () => {
expectError(403, FORBIDDEN, response)
})
})

describe(`PATCH ${endpointUrl}:id`, () => {
it('should update a question', async () => {
const response = await app
.patch(endpointUrl + testQuestionId)
.send(updateData)
.set('Authorization', `Bearer ${accessToken}`)
expect(response.statusCode).toBe(204)

const updatedQuestion = await Question.findById(testQuestionId)

expect(updatedQuestion).toMatchObject({
...testQuestionData,
...updateData
})
})

it('should throw UNAUTHORIZED', async () => {
const response = await app.patch(endpointUrl + testQuestionId).send(updateData)

expectError(401, UNAUTHORIZED, response)
})

it('should throw FORBIDDEN', async () => {
const response = await app
.patch(endpointUrl + testQuestionId)
.send(updateData)
.set('Authorization', `Bearer ${studentAccessToken}`)

expectError(403, FORBIDDEN, response)
})
})
})

0 comments on commit 3094684

Please sign in to comment.