Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Company Application Status #349

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
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
21 changes: 12 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 13 additions & 7 deletions src/models/CompanyApplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,22 @@ export const CompanyApplicationProps = {
return !!this.rejectedAt;
},
},
state: {
type: String,
enum: ApplicationStatus,
default: function() {
if (this.rejectedAt) return ApplicationStatus.REJECTED;
if (this.approvedAt) return ApplicationStatus.APPROVED;
return ApplicationStatus.PENDING;
},
required: true,
},
};

const CompanyApplicationSchema = new Schema(CompanyApplicationProps);

CompanyApplicationSchema.index({ companyName: "text" });

CompanyApplicationSchema.virtual("state").get(function() {
if (!this.approvedAt && !this.rejectedAt) return ApplicationStatus.PENDING;
else if (this.approvedAt) return ApplicationStatus.APPROVED;
else return ApplicationStatus.REJECTED;
});

async function validateEmailUniqueAccount(value) {
try {
await checkDuplicatedEmail(value);
Expand All @@ -107,7 +111,6 @@ function validateDecisionDate(value) {
}

function validateMutuallyExclusiveEvents(field) {

return function(value) {
return !value || !this[field];
};
Expand Down Expand Up @@ -153,6 +156,7 @@ export const isRejectable = (application) => {
CompanyApplicationSchema.methods.approve = function() {
isApprovable(this);
this.approvedAt = Date.now();
this.state = ApplicationStatus.APPROVED;
// Need to prevent validation, otherwise it will fail the email uniqueness,
// Since there is already an application with same email: itself :)
return this.save({ validateModifiedOnly: true });
Expand All @@ -162,6 +166,7 @@ CompanyApplicationSchema.methods.reject = function(reason) {
isRejectable(this);
this.rejectedAt = Date.now();
this.rejectReason = reason;
this.state = ApplicationStatus.REJECTED;
// Need to prevent validation, otherwise it will fail the email uniqueness,
// Since there is already an application with same email: itself :)
return this.save({ validateModifiedOnly: true });
Expand All @@ -170,6 +175,7 @@ CompanyApplicationSchema.methods.reject = function(reason) {
CompanyApplicationSchema.methods.undoApproval = function() {
if (!this.approvedAt) throw new Error("Cannot undo approval of yet-to-be approved Company Application");
this.approvedAt = undefined;
this.state = ApplicationStatus.PENDING;
// Need to prevent validation, otherwise it will fail the email uniqueness,
// Since there is already an application with same email: itself :)
return this.save({ validateModifiedOnly: true });
Expand Down
116 changes: 102 additions & 14 deletions test/company_application_schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,122 @@ describe("# CompanyApplication schema tests", () => {
companyApplicationTester.maxLength("rejectReason", CompanyApplicationConstants.rejectReason.max_length);
});

describe("Virtual field tests", () => {
describe("Test `status` virtual field", () => {
test("should return PENDING", () => {
const application = new CompanyApplication({
submittedAt: new Date("01/01/2020"),
describe("Application Status tests", () => {
const rejectReason = "Rejected for a good reason";
const submittedAt = new Date("01/01/2020");
const baseApplication = {
submittedAt: submittedAt,
companyName: "Testing company",
password: "password123",
motivation: "This company has a very valid motivation because otherwise, the tests would not exist.",
};
beforeAll(async () => {
await CompanyApplication.deleteMany({});
});
afterAll(async () => {
await CompanyApplication.deleteMany({});
});

describe("Approve and reject functions", () => {
test("should return PENDING", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]"
});

expect(application.state).toBe(ApplicationStatus.PENDING);

expect(application.rejectedAt).toBeUndefined();
expect(application.approvedAt).toBeUndefined();
expect(application.rejectReason).toBeUndefined();
});

test("should return REJECTED", () => {
const application = new CompanyApplication({
submittedAt: new Date("01/01/2020"),
rejectedAt: new Date("02/01/2020"),
test("should return REJECTED", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]"
});
await application.reject(rejectReason);

expect(application.state).toBe(ApplicationStatus.REJECTED);
expect(application.rejectReason).toBe(rejectReason);
expect(application.rejectedAt).toBeDefined();

expect(application.approvedAt).toBeUndefined();
});

test("should return APPROVED", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]"
});
await application.approve();

expect(application.state).toBe(ApplicationStatus.APPROVED);
expect(application.approvedAt).toBeDefined();

expect(application.rejectedAt).toBeUndefined();
expect(application.rejectReason).toBeUndefined();
});

test("should return APPROVED", () => {
const application = new CompanyApplication({
submittedAt: new Date("01/01/2020"),
approvedAt: new Date("02/01/2020"),
test("should return PENDING after undoApproval", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]"
});

await application.approve();
expect(application.state).toBe(ApplicationStatus.APPROVED);

await application.undoApproval();
expect(application.state).toBe(ApplicationStatus.PENDING);

expect(application.rejectedAt).toBeUndefined();
expect(application.approvedAt).toBeUndefined();
expect(application.rejectReason).toBeUndefined();
});

test("should throw error when trying to approve a rejected application", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]",
});

await application.reject(rejectReason);
expect(() => application.approve()).toThrow();
});

test("should throw error when trying to reject an approved application", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]",
});

await application.approve();
expect(() => application.reject(rejectReason)).toThrow();
});
});
});

describe("Migration of application state with correct default value", () => {
const assessedAt = new Date(submittedAt.getTime() + 1);
test("should return APPROVED if approvedAt is defined", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]",
approvedAt: assessedAt,
});
expect(application.state).toBe(ApplicationStatus.APPROVED);
});

test("should return REJECTED if rejectedAt is defined", async () => {
const application = await CompanyApplication.create({
...baseApplication,
email: "[email protected]",
rejectedAt: assessedAt,
rejectReason: rejectReason,
});
expect(application.state).toBe(ApplicationStatus.REJECTED);
});
});
});
});
3 changes: 3 additions & 0 deletions test/end-to-end/review.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,15 @@ describe("Company application review endpoint test", () => {
...pendingApplication,
submittedAt: new Date("2019-11-24"),
approvedAt: pendingApplication.submittedAt.getTime() + 1,
state: ApplicationStatus.APPROVED,
companyName: "approved Testing company",
email: `approved${pendingApplication.email}`,
};

const rejectedApplication = { ...pendingApplication,
submittedAt: new Date("2019-11-23"),
rejectedAt: pendingApplication.submittedAt.getTime() + 1,
state: ApplicationStatus.REJECTED,
companyName: "rejected Testing company",
email: `rejected${pendingApplication.email}`,
rejectReason: "2bad4nij0bs",
Expand Down
Loading