Skip to content
Open
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
2 changes: 2 additions & 0 deletions controllers/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ const updateApplication = async (req: CustomRequest, res: CustomResponse) => {
return res.boom.notFound(APPLICATION_ERROR_MESSAGES.APPLICATION_NOT_FOUND);
case APPLICATION_STATUS.unauthorized:
return res.boom.unauthorized(APPLICATION_ERROR_MESSAGES.APPLICATION_EDIT_UNAUTHORIZED);
case APPLICATION_STATUS.notPending:
return res.boom.conflict(APPLICATION_ERROR_MESSAGES.APPLICATION_ALREADY_REVIEWED);
case APPLICATION_STATUS.tooSoon:
return res.boom.conflict(APPLICATION_ERROR_MESSAGES.EDIT_TOO_SOON);
case APPLICATION_STATUS.success:
Expand Down
10 changes: 10 additions & 0 deletions models/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,15 @@ const updateApplication = async (
return { status: APPLICATION_STATUS.unauthorized };
}

const isEditableApplicationStatus =
application.status === APPLICATION_STATUS_TYPES.PENDING ||
application.status === APPLICATION_STATUS_TYPES.CHANGES_REQUESTED;

if (!isEditableApplicationStatus) {
return { status: APPLICATION_STATUS.notPending };
}


const lastEditAt = application.lastEditAt;
if (lastEditAt) {
const lastEditTimestamp = new Date(lastEditAt).getTime();
Expand All @@ -167,6 +176,7 @@ const updateApplication = async (
const requestBody = {
...dataToUpdate,
lastEditAt: new Date(currentTime).toISOString(),
status: APPLICATION_STATUS_TYPES.PENDING,
};
transaction.update(applicationRef, requestBody);

Expand Down
54 changes: 53 additions & 1 deletion test/integration/application.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ const applicationModel = require("../../models/applications");

const applicationsData = require("../fixtures/applications/applications")();
const cookieName = config.get("userToken.cookieName");
const { APPLICATION_ERROR_MESSAGES, API_RESPONSE_MESSAGES, APPLICATION_SCORE } = require("../../constants/application");
const {
APPLICATION_ERROR_MESSAGES,
API_RESPONSE_MESSAGES,
APPLICATION_SCORE,
APPLICATION_STATUS_TYPES,
} = require("../../constants/application");
const imageService = require("../../services/imageService");
const { Buffer } = require("node:buffer");

Expand Down Expand Up @@ -378,6 +383,34 @@ describe("Application", function () {
});
});

it("should set application status to pending after a successful edit from changes_requested", async function () {
const applicationData = {
...applicationsData[1],
userId,
status: APPLICATION_STATUS_TYPES.CHANGES_REQUESTED,
};
const editableApplicationId = await applicationModel.addApplication(applicationData);

expect(applicationData.status).to.equal(APPLICATION_STATUS_TYPES.CHANGES_REQUESTED);

const patchRes = await chai
.request(app)
.patch(`/applications/${editableApplicationId}`)
.set("cookie", `${cookieName}=${jwt}`)
.send({ introduction: "Updated introduction text" });

expect(patchRes).to.have.status(200);
expect(patchRes.body.message).to.be.equal("Application updated successfully");

const getRes = await chai
.request(app)
.get(`/applications/${editableApplicationId}`)
.set("cookie", `${cookieName}=${superUserJwt}`);

expect(getRes).to.have.status(200);
expect(getRes.body.application.status).to.be.equal("pending");
});

it("should return 400 when request body is empty", function (done) {
chai
.request(app)
Expand Down Expand Up @@ -506,6 +539,25 @@ describe("Application", function () {
expect(secondRes.body.message).to.be.equal(APPLICATION_ERROR_MESSAGES.EDIT_TOO_SOON);
});

it("should return 409 when trying to edit an application that has already been reviewed", async function () {
const reviewedApplicationData = {
...applicationsData[1],
userId,
status: APPLICATION_STATUS_TYPES.ACCEPTED,
};
const reviewedApplicationId = await applicationModel.addApplication(reviewedApplicationData);

const res = await chai
.request(app)
.patch(`/applications/${reviewedApplicationId}`)
.set("cookie", `${cookieName}=${jwt}`)
.send({ introduction: "Attempt edit after review" });

expect(res).to.have.status(409);
expect(res.body.error).to.be.equal("Conflict");
expect(res.body.message).to.be.equal(APPLICATION_ERROR_MESSAGES.APPLICATION_ALREADY_REVIEWED);
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.

it("should return 200 when updating city, state, and country", async function () {
const applicationData = { ...applicationsData[0], userId };
const testApplicationId = await applicationModel.addApplication(applicationData);
Expand Down
10 changes: 10 additions & 0 deletions test/unit/controllers/applications.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ describe("updateApplication", () => {
expect(jsonSpy.called).to.be.false;
});

it("should return 409 when application status is not editable", async () => {
updateApplicationStub.resolves({ status: APPLICATION_STATUS.notPending });

await applicationsController.updateApplication(req as CustomRequest, res as CustomResponse);

expect(boomConflict.calledOnce).to.be.true;
expect(boomConflict.firstCall.args[0]).to.equal(APPLICATION_ERROR_MESSAGES.APPLICATION_ALREADY_REVIEWED);
expect(jsonSpy.called).to.be.false;
});

it("should return 500 when model returns unexpected status", async () => {
updateApplicationStub.resolves({ status: "unknown" });

Expand Down
Loading