Skip to content

Commit

Permalink
add more checks and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
meetulr committed Apr 16, 2024
1 parent 2b8a966 commit 6312382
Show file tree
Hide file tree
Showing 10 changed files with 276 additions and 12 deletions.
2 changes: 2 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"actionItem.notFound": "Action Item not found",
"advertisement.notFound": "Advertisement not found",
"event.notFound": "Event not found",
"baseRecurringEvent.notFound": "Base Recurring Event not found",
"recurrenceRule.notFound": "Recurrence Rule not found",
"organization.notFound": "Organization not found",
"organization.profileImage.notFound": "Organization profile image not found",
"organization.member.notFound": "Organization's user is not a member",
Expand Down
2 changes: 2 additions & 0 deletions locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"actionItemCategory.isDisabled": "La catégorie d'élément d'action est désactivée",
"actionItem.notFound": "Élément d\\’action non trouvé",
"event.notFound": "Événement non trouvé",
"baseRecurringEvent.notFound": "Événement récurrent de base introuvable",
"recurrenceRule.notFound": "Règle de récurrence introuvable",
"organization.notFound": "Organisation introuvable",
"organization.profileImage.notFound": "Image du profil de l'organisation introuvable",
"organization.member.notFound": "L'utilisateur de l'organisation n'est pas membre",
Expand Down
2 changes: 2 additions & 0 deletions locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"actionItem.notFound": "कार्रवाई का मद नहीं मिला",
"advertisement.notFound": "विज्ञापन नहीं मिला",
"event.notFound": "घटना नहीं मिली",
"baseRecurringEvent.notFound": "आधार पुनरावृत्ति कार्यक्रम नहीं मिला",
"recurrenceRule.notFound": "पुनरावृत्ति नियम नहीं मिला",
"organization.notFound": "संगठन नहीं मिला",
"organization.profileImage.notFound": "संगठन की प्रोफ़ाइल छवि नहीं मिली",
"organization.member.notFound": "संगठन का उपयोगकर्ता सदस्य नहीं है",
Expand Down
2 changes: 2 additions & 0 deletions locales/sp.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"actionItemCategory.isDisabled": "La categoría de elemento de acción está deshabilitada",
"actionItem.notFound": "Elemento de acción no encontrado",
"event.notFound": "Evento no encontrado",
"baseRecurringEvent.notFound": "Evento recurrente base no encontrado",
"recurrenceRule.notFound": "Regla de recurrencia no encontrada",
"organization.notFound": "Organización no encontrada",
"organization.profileImage.notFound": "No se encontró la imagen del perfil de la organización",
"organization.member.notFound": "El usuario de la organización no es miembro",
Expand Down
2 changes: 2 additions & 0 deletions locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"actionItemCategory.isDisabled": "操作项类别已禁用",
"actionItem.notFound": "找不到操作项",
"event.notFound": "未找到事件",
"baseRecurringEvent.notFound": "未找到基本重复事件",
"recurrenceRule.notFound": "未找到重复规则",
"organization.notFound": "未找到組織",
"organization.profileImage.notFound": "未找到組織檔案圖像",
"organization.member.notFound": "組織的用戶不是成員",
Expand Down
16 changes: 16 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const ACTION_ITEM_CATEGORY_ALREADY_EXISTS = {
MESSAGE: "actionItemCategory.alreadyExists",
PARAM: "actionItemCategory",
};

export const ACTION_ITEM_CATEGORY_IS_DISABLED = {
DESC: "Action Item Category is disabled",
CODE: "actionItemCategory.isDisabled",
Expand All @@ -42,6 +43,13 @@ export const AGENDA_CATEGORY_NOT_FOUND_ERROR = {
PARAM: "agendaCategory",
};

export const BASE_RECURRING_EVENT_NOT_FOUND = {
DESC: "Base Recurring Event not found",
CODE: "baseRecurringEvent.notFound",
MESSAGE: "baseRecurringEvent.notFound",
PARAM: "baseRecurringEvent",
};

export const CHAT_NOT_FOUND_ERROR = {
DESC: "Chat not found",
CODE: "chat.notFound",
Expand Down Expand Up @@ -174,6 +182,14 @@ export const ORGANIZATION_NOT_FOUND_ERROR = {
MESSAGE: "organization.notFound",
PARAM: "organization",
};

export const RECURRENCE_RULE_NOT_FOUND = {
DESC: "Recurrence Rule not found",
CODE: "recurrenceRule.notFound",
MESSAGE: "recurrenceRule.notFound",
PARAM: "recurrenceRule",
};

export const VENUE_NAME_MISSING_ERROR = {
DESC: "Venue name not found",
CODE: "venueName.notFound",
Expand Down
35 changes: 29 additions & 6 deletions src/helpers/event/deleteEventHelpers/deleteRecurringEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import type { InterfaceEvent } from "../../../models";
import { Event, RecurrenceRule } from "../../../models";
import type { MutationRemoveEventArgs } from "../../../types/generatedGraphQLTypes";
import { deleteRecurringEventInstances, deleteSingleEvent } from "./index";
import { errors, requestContext } from "../../../libraries";
import {
BASE_RECURRING_EVENT_NOT_FOUND,
RECURRENCE_RULE_NOT_FOUND,
} from "../../../constants";

/**
* This function deletes thisInstance / allInstances / thisAndFollowingInstances of a recurring event.
Expand All @@ -20,15 +25,33 @@ export const deleteRecurringEvent = async (
session: mongoose.ClientSession,
): Promise<void> => {
// get the recurrenceRule
const recurrenceRule = await RecurrenceRule.find({
const recurrenceRule = await RecurrenceRule.findOne({
_id: event.recurrenceRuleId,
});

// throws error if the recurrence rule doesn't exist
if (recurrenceRule === null) {
throw new errors.NotFoundError(
requestContext.translate(RECURRENCE_RULE_NOT_FOUND.MESSAGE),
RECURRENCE_RULE_NOT_FOUND.CODE,
RECURRENCE_RULE_NOT_FOUND.PARAM,
);
}

// get the baseRecurringEvent
const baseRecurringEvent = await Event.find({
const baseRecurringEvent = await Event.findOne({
_id: event.baseRecurringEventId,
});

// throws error if the base recurring event doesn't exist
if (baseRecurringEvent === null) {
throw new errors.NotFoundError(
requestContext.translate(BASE_RECURRING_EVENT_NOT_FOUND.MESSAGE),
BASE_RECURRING_EVENT_NOT_FOUND.CODE,
BASE_RECURRING_EVENT_NOT_FOUND.PARAM,
);
}

if (
event.isRecurringEventException ||
args.recurringEventDeleteType === "thisInstance"
Expand All @@ -41,17 +64,17 @@ export const deleteRecurringEvent = async (
// and update the recurrenceRule and baseRecurringEvent accordingly
await deleteRecurringEventInstances(
null, // because we're going to delete all the instances, which we could get from the recurrence rule
recurrenceRule[0],
baseRecurringEvent[0],
recurrenceRule,
baseRecurringEvent,
session,
);
} else {
// delete this and following the instances
// and update the recurrenceRule and baseRecurringEvent accordingly
await deleteRecurringEventInstances(
event, // we'll find all the instances after(and including) this one and delete them
recurrenceRule[0],
baseRecurringEvent[0],
recurrenceRule,
baseRecurringEvent,
session,
);
}
Expand Down
35 changes: 29 additions & 6 deletions src/helpers/event/updateEventHelpers/updateRecurringEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { Event, RecurrenceRule } from "../../../models";
import type { MutationUpdateEventArgs } from "../../../types/generatedGraphQLTypes";
import { updateThisInstance } from "./updateThisInstance";
import { updateRecurringEventInstances } from "./updateRecurringEventInstances";
import { errors, requestContext } from "../../../libraries";
import {
BASE_RECURRING_EVENT_NOT_FOUND,
RECURRENCE_RULE_NOT_FOUND,
} from "../../../constants";

/**
* This function updates the recurring event.
Expand All @@ -24,15 +29,33 @@ export const updateRecurringEvent = async (
let updatedEvent: InterfaceEvent = event;

// get the recurrenceRule
const recurrenceRule = await RecurrenceRule.find({
const recurrenceRule = await RecurrenceRule.findOne({
_id: event.recurrenceRuleId,
});

// throws error if the recurrence rule doesn't exist
if (recurrenceRule === null) {
throw new errors.NotFoundError(
requestContext.translate(RECURRENCE_RULE_NOT_FOUND.MESSAGE),
RECURRENCE_RULE_NOT_FOUND.CODE,
RECURRENCE_RULE_NOT_FOUND.PARAM,
);
}

// get the baseRecurringEvent
const baseRecurringEvent = await Event.find({
const baseRecurringEvent = await Event.findOne({
_id: event.baseRecurringEventId,
});

// throws error if the base recurring event doesn't exist
if (baseRecurringEvent === null) {
throw new errors.NotFoundError(
requestContext.translate(BASE_RECURRING_EVENT_NOT_FOUND.MESSAGE),
BASE_RECURRING_EVENT_NOT_FOUND.CODE,
BASE_RECURRING_EVENT_NOT_FOUND.PARAM,
);
}

if (
(args.data?.isRecurringEventException !== undefined &&
args.data?.isRecurringEventException !==
Expand All @@ -46,8 +69,8 @@ export const updateRecurringEvent = async (
updatedEvent = await updateRecurringEventInstances(
args,
event,
recurrenceRule[0],
baseRecurringEvent[0],
recurrenceRule,
baseRecurringEvent,
"allInstances",
session,
);
Expand All @@ -56,8 +79,8 @@ export const updateRecurringEvent = async (
updatedEvent = await updateRecurringEventInstances(
args,
event,
recurrenceRule[0],
baseRecurringEvent[0],
recurrenceRule,
baseRecurringEvent,
"thisAndFollowingInstances",
session,
);
Expand Down
110 changes: 110 additions & 0 deletions tests/resolvers/Mutation/removeEvent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import {

import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import {
BASE_RECURRING_EVENT_NOT_FOUND,
EVENT_NOT_FOUND_ERROR,
RECURRENCE_RULE_NOT_FOUND,
USER_NOT_AUTHORIZED_ERROR,
USER_NOT_FOUND_ERROR,
} from "../../../src/constants";
Expand Down Expand Up @@ -890,6 +892,114 @@ describe("resolvers -> Mutation -> removeEvent", () => {
);
});

it(`throws not found error if the base recurring event doesn't exist`, async () => {
const { requestContext } = await import("../../../src/libraries");
const spy = vi
.spyOn(requestContext, "translate")
.mockImplementation((message) => `Translated ${message}`);

try {
let startDate = new Date();
startDate = convertToUTCDate(startDate);
const endDate = startDate;

const createEventArgs: MutationCreateEventArgs = {
data: {
organizationId: testOrganization?.id,
allDay: true,
description: "newDescription",
endDate,
isPublic: false,
isRegisterable: false,
latitude: 1,
longitude: 1,
location: "newLocation",
recurring: true,
startDate,
title: "newTitle",
},
recurrenceRuleData: {
recurrenceStartDate: startDate,
recurrenceEndDate: convertToUTCDate(addMonths(startDate, 6)),
frequency: "WEEKLY",
},
};

const createEventContext = {
userId: testUser?.id,
};

const { createEvent: createEventResolver } = await import(
"../../../src/resolvers/Mutation/createEvent"
);

testRecurringEvent = (await createEventResolver?.(
{},
createEventArgs,
createEventContext,
)) as InterfaceEvent;

// delete the base recurring event
await Event.deleteOne({
_id: testRecurringEvent.baseRecurringEventId,
});

const args: MutationRemoveEventArgs = {
id: testRecurringEvent?._id.toString(),
recurringEventDeleteType: "thisInstance",
};

const context = {
userId: testUser?.id,
};

await removeEventResolver?.({}, args, context);
} catch (error: unknown) {
expect(spy).toHaveBeenCalledWith(BASE_RECURRING_EVENT_NOT_FOUND.MESSAGE);
if (error instanceof Error) {
expect(error.message).toEqual(
`Translated ${BASE_RECURRING_EVENT_NOT_FOUND.MESSAGE}`,
);
} else {
fail(`Expected NotFoundError, but got ${error}`);
}
}
});

it(`throws not found error if the recurrence rule doesn't exist`, async () => {
const { requestContext } = await import("../../../src/libraries");
const spy = vi
.spyOn(requestContext, "translate")
.mockImplementation((message) => `Translated ${message}`);

try {
// delete the base recurrence rule
await RecurrenceRule.deleteOne({
_id: testRecurringEvent.recurrenceRuleId,
});

const args: MutationRemoveEventArgs = {
id: testRecurringEvent?._id.toString(),
recurringEventDeleteType: "thisInstance",
};

const context = {
userId: testUser?.id,
};

await removeEventResolver?.({}, args, context);
} catch (error: unknown) {
expect(spy).toHaveBeenCalledWith(RECURRENCE_RULE_NOT_FOUND.MESSAGE);
if (error instanceof Error) {
expect(error.message).toEqual(
`Translated ${RECURRENCE_RULE_NOT_FOUND.MESSAGE}`,
);
} else {
fail(`Expected NotFoundError, but got ${error}`);
}
}
});

it("throws an error if user does not have appUserProfile", async () => {
const { requestContext } = await import("../../../src/libraries");
const spy = vi
Expand Down
Loading

0 comments on commit 6312382

Please sign in to comment.