Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 68 additions & 3 deletions _apidoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,35 @@
* attainment as per Bloom's Taxanomy (L1-L6).
*/

// ------------------------------------------------------------------------------------------
// Group.
// ------------------------------------------------------------------------------------------

/**
* @api {post} /group/add Add Group
* @apiName AddGroup
* @apiGroup Group
* @apiDescription Add a new group.
*
* @apiBody {String} title Group title.
* @apiBody {ObjectId[]} students Array of student ObjectIDs.
*
* @apiSuccess {String} res Response message.
* @apiError (Error 500) GroupAddError Error while adding the group
*
* @apiSuccessExample Success-Response:
* HTTP/1.1 200 OK
* {
* "res": "added group Example Group"
* }
*
* @apiErrorExample Error-Response:
* HTTP/1.1 500 Internal Server Error
* {
* "err": "Error while inserting in DB"
* }
*/

// ------------------------------------------------------------------------------------------
// Semester
// ------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -757,9 +786,6 @@
* @apiError (Error 500) DatabaseError Error while inserting in the database.
*
* @apiDescription Adds a new Activity to the system.
*/

/**
*
* @apiSuccessExample Success-Response:
* HTTP/1.1 200 OK
Expand All @@ -774,6 +800,45 @@
* }
*/

/**
* @api {delete} /group/delete/:id Delete Group
* @apiName DeleteGroup
* @apiGroup Group
*
* @apiParam {ObjectId} id The ObjectID of the group to delete.
*
* @apiSuccess {String} res Success message indicating the deletion.
* @apiError (Error 500) GroupDeleteError Error while deleting the group
*
*/

/**
* @api {post} /group/update/:id Update Group Details
* @apiName UpdateGroup
* @apiGroup Group
* @apiDescription Update existing group details.
*
* @apiParam {ObjectId} id The ObjectID of the group to update.
* @apiBody {String} [title] Group title.
* @apiBody {ObjectId[]} [students] Array of student ObjectIDs.
*
* @apiSuccess {String} res Group updated.
* @apiError (Error 500) GroupUpdateError Error in updating database
*
*/

/**
* @api {get} /group/list Get Group List
* @apiName GetGroupList
* @apiGroup Group
*
* @apiQuery {String} [title] Title of the group.
*
* @apiSuccess {Group[]} res Array of filtered group documents.
* @apiSuccess {ObjectId} group._id ObjectID of the group document in the database.
* @apiSuccess {String} group.title Title of the group.
* @apiSuccess {ObjectId[]} group.students Array of student ObjectIDs in the group.
*/
/**
* @api {delete} /timetable/delete/:timetableId Delete Timetable
* @apiName DeleteTimetable
Expand Down
2 changes: 2 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import moduleRouter from "#routes/module";
import facultyRouter from "#routes/faculty";
import { identifyUser } from "#middleware/identifyUser";
import departmentRouter from "#routes/department";
import groupRouter from "#routes/group";

const app = express();
const currDirName = dirname(fileURLToPath(import.meta.url));
Expand Down Expand Up @@ -56,6 +57,7 @@ app.use("/timetable", timetableRouter);
app.use("/department", departmentRouter);
app.use("/coursework", courseworkRouter);
app.use("/module", moduleRouter);
app.use("/group", groupRouter);
app.use("/semester", semesterRouter);
app.use("/faculty", facultyRouter);
export default app;
54 changes: 54 additions & 0 deletions controller/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
createGroup, deleteGroupById, groupList, updateGroupById,
} from "#services/group";
import { logger } from "#util";

async function addGroup(req, res) {
const {
title, student,
} = req.body;
try {
const group = await createGroup(title, student);
res.json({ res: `added group ${group.id}`, id: group.id });
} catch (error) {
logger.error("Error while inserting", error);
res.status(500);
res.json({ err: "Error while inserting in DB" });
}
}

async function updateGroup(req, res) {
const { id } = req.params;
const {
...data
} = req.body;
try {
await updateGroupById(id, data);
res.json({ res: `updated group with id ${id}` });
} catch (error) {
logger.error("Error while updating", error);
res.status(500);
res.json({ err: "Error while updaing in DB" });
}
}

async function getGroup(req, res) {
const filter = req.query;
const group = await groupList(filter);
res.json({ res: group });
}

async function deleteGroup(req, res) {
const { id } = req.params;
try {
await deleteGroupById(id);
res.json({ res: `Deleted group with ID ${id}` });
} catch (error) {
logger.error("Error while deleting", error);
res.status(500).json({ error: "Error while deleting from DB" });
}
}

export default {
addGroup, deleteGroup, getGroup, updateGroup,
};
2 changes: 1 addition & 1 deletion models/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async function read(filter, limit = 1) {
}

async function update(filter, updateObject, options = { multi: true }) {
const updateResult = await Group.updateManyupdateMany(filter, { $set: updateObject }, options);
const updateResult = await Group.updateMany(filter, { $set: updateObject }, options);
return updateResult.acknowledged;
}
async function remove(groupId) {
Expand Down
10 changes: 10 additions & 0 deletions routes/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import express from "express";
import groupController from "#controller/group";

const router = express.Router();
router.post("/add", groupController.addGroup);
router.get("/list", groupController.getGroup);
router.post("/update/:id", groupController.updateGroup);
router.delete("/delete/:id", groupController.deleteGroup);

export default router;
33 changes: 33 additions & 0 deletions services/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Group from "#models/group";
import databaseError from "#error/database";

export async function createGroup(title, student) {
const newGroup = await Group.create({
title, student,
});
if (newGroup.title === title) {
return newGroup;
}
throw new databaseError.DataEntryError("group");
}

export async function updateGroupById(id, data) {
const updated = await Group.update({ _id: id }, data);
if (updated) {
return updated;
}
throw new databaseError.DataEntryError("group");
}

export async function groupList(filter) {
const groups = await Group.read(filter, 0);
return groups;
}

export async function deleteGroupById(groupId) {
const deleted = await Group.remove({ _id: groupId });
if (deleted) {
return deleted;
}
throw new databaseError.DataDeleteError("group");
}
84 changes: 84 additions & 0 deletions test/routes/group.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { jest } from "@jest/globals"; // eslint-disable-line import/no-extraneous-dependencies
import request from "supertest";
import app from "#app";
import connector from "#models/databaseUtil";
import groupModel from "#models/group";

jest.mock("#util");

let server;
let agent;

beforeAll((done) => {
server = app.listen(null, () => {
agent = request.agent(server);
connector.set("debug", false);
done();
});
});

function cleanUp(callback) {
groupModel
.remove({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should pass only id as parameter in remove(delete) operation not with title because in group models we are taking only groupId as input

id: "6500594e2b7b532006c073dd",
})
.then(() => {
connector.disconnect((DBerr) => {
if (DBerr) console.log("Database disconnect error: ", DBerr);
server.close((serverErr) => {
if (serverErr) console.log(serverErr);
callback();
});
});
});
}

afterAll((done) => {
cleanUp(done);
});

describe("group API", () => {
it("should create group", async () => {
const response = await agent.post("/group/add").send({
title: "Group 1",
student: "64fdc67feca8a69f01b33614",
});
expect(response.headers["content-type"]).toMatch(/json/);
expect(response.status).toBe(200);
expect(response.body.res).toMatch(/added group/);
});

describe("after adding group", () => {
let id;
beforeEach(async () => {
id = await agent.post("/group/add").send({
title: "Group 1",
student: "64fdc67feca8a69f01b33614",
});
id = JSON.parse(id.res.text).id;
});

afterEach(async () => {
await groupModel.remove({
id: "6500594e2b7b532006c073dd",
});
});

it("should read group", async () => {
const response = await agent
.get("/group/list")
.send({ name: "Building A" });
expect(response.status).toBe(200);
expect(response.body.res).toBeDefined();
});

it("should update group", async () => {
const response = await agent
.post(`/group/update/${id}`)
.send({ title: "Group 1" }, { title: "Group 2" });
expect(response.headers["content-type"]).toMatch(/json/);
expect(response.status).toBe(200);
expect(response.body.res).toMatch(/updated group/);
});
});
});