diff --git a/server/__tests__/answers.test.js b/server/__tests__/answers.test.js index 27330f7..ac29537 100644 --- a/server/__tests__/answers.test.js +++ b/server/__tests__/answers.test.js @@ -1,28 +1,32 @@ const request = require('supertest'); const express = require('express'); const bodyParser = require('body-parser'); -const answersRouter = require('../routers/answers.js'); -const Answer = require('../models/answer'); +const answersRouter = require('../routers/answers'); // Ensure the correct path +const Answer = require('../models/answers'); const app = express(); -const cors = require("cors"); -app.use(cors()); -app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use('/api', answersRouter); +// Mock the Answer model methods +jest.mock('../models/answers'); + describe('Answers API', () => { beforeEach(() => { - // Reset the in-memory database before each test - while (Answer.getAll().length > 0) { - Answer.delete(Answer.getAll()[0].id); - } + // Clear all instances and calls to constructor and all methods: + Answer.create.mockClear(); + Answer.get.mockClear(); + Answer.getAll.mockClear(); + Answer.delete.mockClear(); }); test('should create a new answer', async () => { + const mockAnswer = { id: 1, answerText: 'This is an answer', showFeedback: true, points: 10 }; + Answer.create.mockReturnValue(mockAnswer); + const response = await request(app) .post('/api/answers') - .send({ answerText: 'This is an answer', showFeedback: true, points: 10,goodAnswer: true}); + .send({ answerText: 'This is an answer', showFeedback: true, points: 10 }); expect(response.status).toBe(200); expect(response.body.message).toBe('Answer created successfully.'); @@ -30,23 +34,23 @@ describe('Answers API', () => { expect(response.body.answer.answerText).toBe('This is an answer'); expect(response.body.answer.showFeedback).toBe(true); expect(response.body.answer.points).toBe(10); - expect(response.body.answer.goodAnswer).toBe(true); - }); test('should get an answer by ID', async () => { - const answer = Answer.create('This is an answer', true, 10, true); - const response = await request(app).get(`/api/answers/${answer.id}`); + const mockAnswer = { id: 1, answerText: 'This is an answer', showFeedback: true, points: 10 }; + Answer.get.mockReturnValue(mockAnswer); + + const response = await request(app).get(`/api/answers/1`); expect(response.status).toBe(200); expect(response.body.answerText).toBe('This is an answer'); expect(response.body.showFeedback).toBe(true); expect(response.body.points).toBe(10); - expect(response.body.goodAnswer).toBe(true); - }); test('should return 404 if answer not found', async () => { + Answer.get.mockReturnValue(null); + const response = await request(app).get('/api/answers/999'); expect(response.status).toBe(404); @@ -54,17 +58,21 @@ describe('Answers API', () => { }); test('should delete an answer by ID', async () => { - const answer = Answer.create('This is an answer', true, 10); - const response = await request(app).delete(`/api/answers/${answer.id}`); + const mockAnswer = { id: 1, answerText: 'This is an answer', showFeedback: true, points: 10 }; + Answer.delete.mockReturnValue(mockAnswer); + + const response = await request(app).delete(`/api/answers/1`); expect(response.status).toBe(200); expect(response.body.message).toBe('Answer deleted successfully.'); - const getResponse = await request(app).get(`/api/answers/${answer.id}`); + const getResponse = await request(app).get(`/api/answers/1`); expect(getResponse.status).toBe(404); }); test('should return 404 if deleting an answer that does not exist', async () => { + Answer.delete.mockReturnValue(null); + const response = await request(app).delete('/api/answers/999'); expect(response.status).toBe(404); diff --git a/server/app.js b/server/app.js index 297dbe6..89573c6 100644 --- a/server/app.js +++ b/server/app.js @@ -22,6 +22,8 @@ const students = require('./models/students.js'); const studentModel = new students(); const answers = require('./models/answers.js'); const answersModel = new answers(); +const quizzes = require('./models/quizzes.js'); +const quizzesModel = new quizzes(); // instantiate the controllers const usersController = require('./controllers/users.js'); @@ -36,6 +38,8 @@ const studentsController = require('./controllers/students.js'); const studentsControllerInstance = new studentsController(studentModel); const answersController = require('./controllers/answers.js'); const answersControllerInstance = new answersController(answersModel); +const quizzesController = require('./controllers/quizzes.js'); +const quizzesControllerInstance = new quizzesController(quizzesModel); // export the controllers module.exports.users = usersControllerInstance; @@ -44,6 +48,7 @@ module.exports.questionnaires = questionnaireControllerInstance; module.exports.images = imagesControllerInstance; module.exports.students = studentsControllerInstance; module.exports.answers = answersControllerInstance; +module.exports.quizzes = quizzesControllerInstance; //import routers (instantiate controllers as side effect) const userRouter = require('./routers/users.js'); @@ -52,6 +57,7 @@ const questionnaireRouter = require('./routers/questionnaires.js'); const imagesRouter = require('./routers/images.js'); const studentsRouter = require('./routers/students.js'); const answersRouter = require('./routers/answers.js'); +const quizzesRouter = require('./routers/quizzes.js'); // Setup environment dotenv.config(); @@ -98,6 +104,7 @@ app.use('/api/questionnaire', questionnaireRouter); app.use('/api/image', imagesRouter); app.use('/api/students', studentsRouter); app.use('/api/answers', answersRouter); +app.use('/api/quizzes', quizzesRouter); app.use(errorHandler); diff --git a/server/controllers/quizzes.js b/server/controllers/quizzes.js new file mode 100644 index 0000000..06d3fae --- /dev/null +++ b/server/controllers/quizzes.js @@ -0,0 +1,74 @@ +const AppError = require('../middleware/AppError.js'); +const { MISSING_REQUIRED_PARAMETER, QUIZ_NOT_FOUND } = require('../constants/errorCodes.js'); + +class QuizController { + constructor(quizModel) { + this.quizzes = quizModel; + } + + create = async (req, res, next) => { + try { + const { students, questionnaire } = req.body; + + if (!students || !questionnaire) { + throw new AppError(MISSING_REQUIRED_PARAMETER); + } + + const result = this.quizzes.create(students, questionnaire); + + return res.status(200).json({ + message: 'Quiz created successfully.', + quiz: result + }); + + } catch (error) { + return next(error); + } + }; + + get = async (req, res, next) => { + try { + const { quizId } = req.params; + + if (!quizId) { + throw new AppError(MISSING_REQUIRED_PARAMETER); + } + + const quiz = this.quizzes.get(parseInt(quizId)); + + if (!quiz) { + throw new AppError(QUIZ_NOT_FOUND); + } + + return res.status(200).json(quiz); + + } catch (error) { + return next(error); + } + }; + + delete = async (req, res, next) => { + try { + const { quizId } = req.params; + + if (!quizId) { + throw new AppError(MISSING_REQUIRED_PARAMETER); + } + + const result = this.quizzes.delete(parseInt(quizId)); + + if (!result) { + throw new AppError(QUIZ_NOT_FOUND); + } + + return res.status(200).json({ + message: 'Quiz deleted successfully.' + }); + + } catch (error) { + return next(error); + } + }; +} + +module.exports = QuizController; \ No newline at end of file diff --git a/server/models/quizzes.js b/server/models/quizzes.js new file mode 100644 index 0000000..84e5420 --- /dev/null +++ b/server/models/quizzes.js @@ -0,0 +1,37 @@ +let quizzes = []; // This will act as our in-memory database + +class Quiz { + constructor(students, questionnaire) { + this.id = Quiz.generateId(); + this.students = students; + this.questionnaire = questionnaire; + } + + static generateId() { + return quizzes.length ? quizzes[quizzes.length - 1].id + 1 : 1; + } + + static create(students, questionnaire) { + const quiz = new Quiz(students, questionnaire); + quizzes.push(quiz); + return quiz; + } + + static get(id) { + return quizzes.find(quiz => quiz.id === id); + } + + static getAll() { + return quizzes; + } + + static delete(id) { + const index = quizzes.findIndex(quiz => quiz.id === id); + if (index !== -1) { + return quizzes.splice(index, 1)[0]; + } + return null; + } +} + +module.exports = Quiz; \ No newline at end of file diff --git a/server/routers/quizzes.js b/server/routers/quizzes.js new file mode 100644 index 0000000..afb78ce --- /dev/null +++ b/server/routers/quizzes.js @@ -0,0 +1,11 @@ +const express = require('express'); +const router = express.Router(); +const quizzes = require('../app.js').quizzes; +const jwt = require('../middleware/jwtToken.js'); +const asyncHandler = require('./routerUtils.js'); + +router.post('/create', jwt.authenticate, asyncHandler(quizzes.create)); +router.get('/get/:quizId',jwt.authenticate, asyncHandler(quizzes.get)); +router.delete('/delete/:quizId', jwt.authenticate, asyncHandler(quizzes.delete)); + +module.exports = router; \ No newline at end of file