Skip to content

Commit cf06175

Browse files
Fix: merge conflicts
2 parents a71b3a6 + e44354d commit cf06175

File tree

4 files changed

+194
-3
lines changed

4 files changed

+194
-3
lines changed

controllers/tasks.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,18 @@ const updateTask = async (req, res) => {
288288
}
289289
}
290290

291+
// currently the task is assigned to a user and the superuser is trying to un assign this task from them.
292+
if (
293+
requestData?.status === TASK_STATUS.AVAILABLE &&
294+
task.taskData.status !== TASK_STATUS.AVAILABLE &&
295+
Object.keys(req.body).length === 1
296+
) {
297+
requestData.assignee = null;
298+
requestData.percentCompleted = 0;
299+
requestData.startedOn = null;
300+
requestData.endsOn = null;
301+
}
302+
291303
await tasks.updateTask(requestData, req.params.id);
292304
if (requestData.assignee) {
293305
// New Assignee Status Update

middlewares/validators/tasks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ const updateTask = async (req, res, next) => {
7979
featureUrl: joi.string().optional(),
8080
type: joi.string().optional(),
8181
links: joi.array().items(joi.string()).optional(),
82-
endsOn: joi.number().optional(),
83-
startedOn: joi.number().optional(),
82+
endsOn: joi.alternatives().try(joi.number().optional(), joi.valid(null)),
83+
startedOn: joi.alternatives().try(joi.number().optional(), joi.valid(null)),
8484
category: joi.string().optional(),
8585
level: joi.number().optional(),
8686
status: joi

test/integration/tasks.test.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,4 +1413,87 @@ describe("Tasks", function () {
14131413
expect(response.status).to.be.equal(400);
14141414
});
14151415
});
1416+
1417+
describe("PATCH /tasks/:id should update the tasks by SuperUser", function () {
1418+
beforeEach(async function () {
1419+
const superUserId = await addUser(superUser);
1420+
superUserJwt = authService.generateAuthToken({ userId: superUserId });
1421+
1422+
await firestore.collection("tasks").doc("4kAkRv9TBlOfR6WEUhoQ").set({
1423+
assignee: "SooJK37gzjIZfFNH0tlL",
1424+
status: "IN_PROGRESS",
1425+
percentCompleted: 80,
1426+
startedOn: 1701388800000,
1427+
endsOn: 1701561600000,
1428+
});
1429+
});
1430+
1431+
afterEach(async function () {
1432+
await firestore.collection("tasks").doc("4kAkRv9TBlOfR6WEUhoQ").delete();
1433+
});
1434+
1435+
it("Should unassign the task with other fields reset exclusively", async function () {
1436+
const res = await chai
1437+
.request(app)
1438+
.patch(`/tasks/4kAkRv9TBlOfR6WEUhoQ`)
1439+
.set("cookie", `${cookieName}=${superUserJwt}`)
1440+
.send({
1441+
assignee: null,
1442+
status: TASK_STATUS.AVAILABLE,
1443+
percentCompleted: 0,
1444+
startedOn: null,
1445+
endsOn: null,
1446+
});
1447+
1448+
expect(res).to.have.status(204);
1449+
1450+
const docSnapshot = await firestore.collection("tasks").doc("4kAkRv9TBlOfR6WEUhoQ").get();
1451+
1452+
const updatedData = docSnapshot.data();
1453+
expect(updatedData.assignee).to.equal(null);
1454+
expect(updatedData.status).to.equal(TASK_STATUS.AVAILABLE);
1455+
expect(updatedData.percentCompleted).to.equal(0);
1456+
expect(updatedData.startedOn).to.equal(null);
1457+
expect(updatedData.endsOn).to.equal(null);
1458+
});
1459+
1460+
it("Should unassign the task with other fields reset internally", async function () {
1461+
const res = await chai
1462+
.request(app)
1463+
.patch(`/tasks/4kAkRv9TBlOfR6WEUhoQ`)
1464+
.set("cookie", `${cookieName}=${superUserJwt}`)
1465+
.send({
1466+
status: TASK_STATUS.AVAILABLE,
1467+
});
1468+
1469+
expect(res).to.have.status(204);
1470+
1471+
const docSnapshot = await firestore.collection("tasks").doc("4kAkRv9TBlOfR6WEUhoQ").get();
1472+
1473+
const updatedData = docSnapshot.data();
1474+
expect(updatedData.assignee).to.equal(null);
1475+
expect(updatedData.status).to.equal(TASK_STATUS.AVAILABLE);
1476+
expect(updatedData.percentCompleted).to.equal(0);
1477+
expect(updatedData.startedOn).to.equal(null);
1478+
expect(updatedData.endsOn).to.equal(null);
1479+
});
1480+
1481+
it("Should throw bad request if the req body is invalid", async function () {
1482+
const res = await chai
1483+
.request(app)
1484+
.patch(`/tasks/4kAkRv9TBlOfR6WEUhoQ`)
1485+
.set("cookie", `${cookieName}=${superUserJwt}`)
1486+
.send({
1487+
assignee: null,
1488+
status: TASK_STATUS.AVAILABLE,
1489+
percentCompleted: 0,
1490+
startedOn: "null",
1491+
endsOn: false,
1492+
});
1493+
1494+
expect(res).to.have.status(400);
1495+
expect(res.body.error).to.equal("Bad Request");
1496+
expect(res.body.message).to.equal('"endsOn" must be one of [number, null]');
1497+
});
1498+
});
14161499
});

test/unit/middlewares/tasks-validator.test.js

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
const Sinon = require("sinon");
2-
const { getTasksValidator, createTask, getUsersValidator } = require("../../../middlewares/validators/tasks");
2+
const {
3+
getTasksValidator,
4+
createTask,
5+
getUsersValidator,
6+
updateTask: updateTaskValidator,
7+
} = require("../../../middlewares/validators/tasks");
38
const { expect } = require("chai");
49
const { TASK_STATUS, tasksUsersStatus } = require("../../../constants/tasks");
510

@@ -521,6 +526,97 @@ describe("getTasks validator", function () {
521526
expect(nextMiddlewareSpy.callCount).to.be.equal(0);
522527
});
523528

529+
it("should call nextMiddlewareSpy for updateTaskValidator if startedOn is null", async function () {
530+
const req = {
531+
body: {
532+
startedOn: null,
533+
endsOn: new Date().getTime(),
534+
},
535+
};
536+
const res = { boom: { badRequest: Sinon.spy() } };
537+
const nextMiddlewareSpy = Sinon.spy();
538+
await updateTaskValidator(req, res, nextMiddlewareSpy);
539+
expect(nextMiddlewareSpy.callCount).to.be.equal(1);
540+
});
541+
542+
it("should call nextMiddlewareSpy for updateTaskValidator if endsOn is null", async function () {
543+
const req = {
544+
body: {
545+
startedOn: new Date().getTime(),
546+
endsOn: null,
547+
},
548+
};
549+
const res = { boom: { badRequest: Sinon.spy() } };
550+
const nextMiddlewareSpy = Sinon.spy();
551+
await updateTaskValidator(req, res, nextMiddlewareSpy);
552+
expect(nextMiddlewareSpy.callCount).to.be.equal(1);
553+
});
554+
555+
it("should call nextMiddlewareSpy for updateTaskValidator if both startedOn and endsOn are null", async function () {
556+
const req = {
557+
body: {
558+
startedOn: null,
559+
endsOn: null,
560+
},
561+
};
562+
const res = { boom: { badRequest: Sinon.spy() } };
563+
const nextMiddlewareSpy = Sinon.spy();
564+
await updateTaskValidator(req, res, nextMiddlewareSpy);
565+
expect(nextMiddlewareSpy.callCount).to.be.equal(1);
566+
});
567+
568+
it("should call nextMiddlewareSpy for updateTaskValidator if both startedOn and endsOn are valid number", async function () {
569+
const req = {
570+
body: {
571+
startedOn: new Date("2023-11-15").getTime(),
572+
endsOn: new Date("2023-11-18").getTime(),
573+
},
574+
};
575+
const res = { boom: { badRequest: Sinon.spy() } };
576+
const nextMiddlewareSpy = Sinon.spy();
577+
await updateTaskValidator(req, res, nextMiddlewareSpy);
578+
expect(nextMiddlewareSpy.callCount).to.be.equal(1);
579+
});
580+
581+
it("should not call nextMiddlewareSpy for updateTaskValidator if startedOn is not null or a number", async function () {
582+
const req = {
583+
body: {
584+
startedOn: "December 6 2023",
585+
endsOn: new Date().getTime(),
586+
},
587+
};
588+
const res = { boom: { badRequest: Sinon.spy() } };
589+
const nextMiddlewareSpy = Sinon.spy();
590+
await updateTaskValidator(req, res, nextMiddlewareSpy);
591+
expect(nextMiddlewareSpy.callCount).to.be.equal(0);
592+
});
593+
594+
it("should not call nextMiddlewareSpy for updateTaskValidator if endsOn is not null or a number", async function () {
595+
const req = {
596+
body: {
597+
startedOn: new Date().getTime(),
598+
endsOn: true,
599+
},
600+
};
601+
const res = { boom: { badRequest: Sinon.spy() } };
602+
const nextMiddlewareSpy = Sinon.spy();
603+
await updateTaskValidator(req, res, nextMiddlewareSpy);
604+
expect(nextMiddlewareSpy.callCount).to.be.equal(0);
605+
});
606+
607+
it("should not call nextMiddlewareSpy for updateTaskValidator if both startedOn and endsOn is not null or a number", async function () {
608+
const req = {
609+
body: {
610+
startedOn: "December 6 2023",
611+
endsOn: true,
612+
},
613+
};
614+
const res = { boom: { badRequest: Sinon.spy() } };
615+
const nextMiddlewareSpy = Sinon.spy();
616+
await updateTaskValidator(req, res, nextMiddlewareSpy);
617+
expect(nextMiddlewareSpy.callCount).to.be.equal(0);
618+
});
619+
524620
describe("getUsersValidator | Validator", function () {
525621
it("should pass the request when valid query parameters are provided", async function () {
526622
const req = {

0 commit comments

Comments
 (0)