diff --git a/codegen.ts b/codegen.ts index 75bbf9f1c6..1a2ab9b479 100644 --- a/codegen.ts +++ b/codegen.ts @@ -46,10 +46,9 @@ const config: CodegenConfig = { Community: "../models/Community#InterfaceCommunity", - DirectChat: "../models/DirectChat#InterfaceDirectChat", + Chat: "../models/Chat#InterfaceChat", - DirectChatMessage: - "../models/DirectChatMessage#InterfaceDirectChatMessage", + ChatMessage: "../models/ChatMessage#InterfaceChatMessage", Donation: "../models/Donation#InterfaceDonation", @@ -75,11 +74,6 @@ const config: CodegenConfig = { Group: "../models/Group#InterfaceGroup", - GroupChat: "../models/GroupChat#InterfaceGroupChat", - - GroupChatMessage: - "../models/GroupChatMessage#InterfaceGroupChatMessage", - // ImageHash: '../models/ImageHash#InterfaceImageHash', Language: "../models/Language#InterfaceLanguage", diff --git a/eslint.config.mjs b/eslint.config.mjs index 8ca9d77075..52481f3548 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -53,7 +53,6 @@ export default [ patterns: ["**/src/**"], }, ], - "import/no-duplicates": "error", "tsdoc/syntax": "error", "@typescript-eslint/ban-ts-comment": "error", diff --git a/schema.graphql b/schema.graphql index 8034bd196d..426398c4f5 100644 --- a/schema.graphql +++ b/schema.graphql @@ -40,7 +40,6 @@ input ActionItemWhereInput { assigneeName: String categoryName: String event_id: ID - is_active: Boolean is_completed: Boolean } @@ -191,6 +190,32 @@ input CampaignWhereInput { organizationId: ID } +type Chat { + _id: ID! + admins: [User] + createdAt: DateTime! + creator: User + image: String + isGroup: Boolean! + lastMessageId: String + messages: [ChatMessage] + name: String + organization: Organization + updatedAt: DateTime! + users: [User!]! +} + +type ChatMessage { + _id: ID! + chatMessageBelongsTo: Chat! + createdAt: DateTime! + deletedBy: [User] + messageContent: String! + replyTo: ChatMessage + sender: User! + updatedAt: DateTime! +} + type CheckIn { _id: ID! createdAt: DateTime! @@ -551,26 +576,6 @@ type DeletePayload { success: Boolean! } -type DirectChat { - _id: ID! - createdAt: DateTime! - creator: User - messages: [DirectChatMessage] - organization: Organization - updatedAt: DateTime! - users: [User!]! -} - -type DirectChatMessage { - _id: ID! - createdAt: DateTime! - directChatMessageBelongsTo: DirectChat! - messageContent: String! - receiver: User! - sender: User! - updatedAt: DateTime! -} - type Donation { _id: ID! amount: Float! @@ -934,26 +939,6 @@ type Group { updatedAt: DateTime! } -type GroupChat { - _id: ID! - createdAt: DateTime! - creator: User - messages: [GroupChatMessage] - organization: Organization! - title: String! - updatedAt: DateTime! - users: [User!]! -} - -type GroupChatMessage { - _id: ID! - createdAt: DateTime! - groupChatMessageBelongsTo: GroupChat! - messageContent: String! - sender: User! - updatedAt: DateTime! -} - type InvalidCursor implements FieldError { message: String! path: [String!]! @@ -1050,16 +1035,6 @@ type Message { videoUrl: URL } -type MessageChat { - _id: ID! - createdAt: DateTime! - languageBarrier: Boolean - message: String! - receiver: User! - sender: User! - updatedAt: DateTime! -} - input MessageChatInput { message: String! receiver: ID! @@ -1086,9 +1061,7 @@ type Mutation { addPledgeToFundraisingCampaign(campaignId: ID!, pledgeId: ID!): FundraisingCampaignPledge! addUserCustomData(dataName: String!, dataValue: Any!, organizationId: ID!): UserCustomData! addUserImage(file: String!): User! - addUserToGroupChat(chatId: ID!, userId: ID!): GroupChat! addUserToUserFamily(familyId: ID!, userId: ID!): UserFamily! - adminRemoveGroup(groupId: ID!): GroupChat! assignUserTag(input: ToggleUserTagAssignInput!): User blockPluginCreationBySuperadmin(blockUser: Boolean!, userId: ID!): AppUserProfile! blockUser(organizationId: ID!, userId: ID!): User! @@ -1102,8 +1075,8 @@ type Mutation { createAgendaCategory(input: CreateAgendaCategoryInput!): AgendaCategory! createAgendaItem(input: CreateAgendaItemInput!): AgendaItem! createAgendaSection(input: CreateAgendaSectionInput!): AgendaSection! + createChat(data: chatInput!): Chat createComment(data: CommentInput!, postId: ID!): Comment - createDirectChat(data: createChatInput!): DirectChat! createDonation(amount: Float!, nameOfOrg: String!, nameOfUser: String!, orgId: ID!, payPalId: ID!, userId: ID!): Donation! createEvent(data: EventInput!, recurrenceRuleData: RecurrenceRuleInput): Event! createEventVolunteer(data: EventVolunteerInput!): EventVolunteer! @@ -1111,9 +1084,7 @@ type Mutation { createFund(data: FundInput!): Fund! createFundraisingCampaign(data: FundCampaignInput!): FundraisingCampaign! createFundraisingCampaignPledge(data: FundCampaignPledgeInput!): FundraisingCampaignPledge! - createGroupChat(data: createGroupChatInput!): GroupChat! createMember(input: UserAndOrganizationInput!): CreateMemberPayload! - createMessageChat(data: MessageChatInput!): MessageChat! createNote(data: NoteInput!): Note! createOrganization(data: OrganizationInput, file: String): Organization! createPlugin(pluginCreatedBy: String!, pluginDesc: String!, pluginName: String!, uninstalledOrgs: [ID!]): Plugin! @@ -1148,13 +1119,11 @@ type Mutation { removeAgendaItem(id: ID!): AgendaItem! removeAgendaSection(id: ID!): ID! removeComment(id: ID!): Comment - removeDirectChat(chatId: ID!, organizationId: ID!): DirectChat! removeEvent(id: ID!, recurringEventDeleteType: RecurringEventMutationType): Event! removeEventAttendee(data: EventAttendeeInput!): User! removeEventVolunteer(id: ID!): EventVolunteer! removeEventVolunteerGroup(id: ID!): EventVolunteerGroup! removeFundraisingCampaignPledge(id: ID!): FundraisingCampaignPledge! - removeGroupChat(chatId: ID!): GroupChat! removeMember(data: UserAndOrganizationInput!): Organization! removeOrganization(id: ID!): UserData! removeOrganizationCustomField(customFieldId: ID!, organizationId: ID!): OrganizationCustomField! @@ -1163,7 +1132,6 @@ type Mutation { removeSampleOrganization: Boolean! removeUserCustomData(organizationId: ID!): UserCustomData! removeUserFamily(familyId: ID!): UserFamily! - removeUserFromGroupChat(chatId: ID!, userId: ID!): GroupChat! removeUserFromUserFamily(familyId: ID!, userId: ID!): UserFamily! removeUserImage: User! removeUserTag(id: ID!): UserTag @@ -1171,8 +1139,7 @@ type Mutation { revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! - sendMessageToDirectChat(chatId: ID!, messageContent: String!): DirectChatMessage! - sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage! + sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID): ChatMessage! signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! unassignUserTag(input: ToggleUserTagAssignInput!): User @@ -1500,12 +1467,11 @@ type Query { agendaItemByEvent(relatedEventId: ID!): [AgendaItem] agendaItemByOrganization(organizationId: ID!): [AgendaItem] agendaItemCategoriesByOrganization(organizationId: ID!): [AgendaCategory] + chatById(id: ID!): Chat! + chatsByUserId(id: ID!): [Chat] checkAuth: User! customDataByOrganization(organizationId: ID!): [UserCustomData!]! customFieldsByOrganization(id: ID!): [OrganizationCustomField] - directChatById(id: ID!): DirectChat - directChatsByUserID(id: ID!): [DirectChat] - directChatsMessagesByChatID(id: ID!): [DirectChatMessage] event(id: ID!): Event eventVolunteersByEvent(id: ID!): [EventVolunteer] eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] @@ -1533,8 +1499,6 @@ type Query { getUserTagAncestors(id: ID!): [UserTag] getVenueByOrgId(first: Int, orderBy: VenueOrderByInput, orgId: ID!, skip: Int, where: VenueWhereInput): [Venue] getlanguage(lang_code: String!): [Translation] - groupChatById(id: ID!): GroupChat - groupChatsByUserId(id: ID!): [GroupChat] hasSubmittedFeedback(eventId: ID!, userId: ID!): Boolean isSampleOrganization(id: ID!): Boolean! joinedOrganizations(id: ID): [Organization] @@ -1635,9 +1599,7 @@ enum Status { } type Subscription { - directMessageChat: MessageChat - messageSentToDirectChat(userId: ID!): DirectChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage + messageSentToChat(userId: ID!): ChatMessage onPluginUpdate: Plugin } @@ -2054,16 +2016,14 @@ enum WeekDays { WEDNESDAY } -input createChatInput { +input chatInput { + image: String + isGroup: Boolean! + name: String organizationId: ID userIds: [ID!]! } -type createDirectChatPayload { - directChat: DirectChat - userErrors: [CreateDirectChatError!]! -} - input createGroupChatInput { organizationId: ID! title: String! diff --git a/src/constants.ts b/src/constants.ts index dcb04c3a95..b4d4d5939d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -64,6 +64,13 @@ export const CHAT_NOT_FOUND_ERROR = Object.freeze({ PARAM: "chat", }); +export const MESSAGE_NOT_FOUND_ERROR = Object.freeze({ + DESC: "Message not found", + CODE: "message.notFound", + MESSAGE: "message.notFound", + PARAM: "message", +}); + export const COMMUNITY_NOT_FOUND_ERROR = Object.freeze({ DESC: "Community not found", CODE: "community.notFound", diff --git a/src/models/DirectChat.ts b/src/models/Chat.ts similarity index 54% rename from src/models/DirectChat.ts rename to src/models/Chat.ts index 3715e0f687..813cd539d4 100644 --- a/src/models/DirectChat.ts +++ b/src/models/Chat.ts @@ -1,34 +1,42 @@ import type { PopulatedDoc, Types, Document, Model } from "mongoose"; import { Schema, model, models } from "mongoose"; -import type { InterfaceDirectChatMessage } from "./DirectChatMessage"; import type { InterfaceOrganization } from "./Organization"; import type { InterfaceUser } from "./User"; import { createLoggingMiddleware } from "../libraries/dbLogger"; +import type { InterfaceChatMessage } from "./ChatMessage"; /** * Interface representing a document for direct chat in MongoDB. */ -export interface InterfaceDirectChat { +export interface InterfaceChat { _id: Types.ObjectId; + isGroup: boolean; + name: string; users: PopulatedDoc[]; - messages: PopulatedDoc[]; + messages: PopulatedDoc[]; creatorId: PopulatedDoc; organization: PopulatedDoc; status: string; + admins: PopulatedDoc[]; createdAt: Date; updatedAt: Date; + lastMessageId: string; } /** - * Mongoose schema for a direct chat. + * Mongoose schema for a chat. + * @param isGroup - Indicates if the chat is a group chat. + * @param name - Name of the chat if its a group chat. * @param users - Users participating in the chat. * @param messages - Messages in the chat. * @param creatorId - Creator of the chat, reference to `User` model. + * @param admins - Admins of the chat if its a group chat, reference to `User` model. * @param organization - Organization associated with the chat, reference to `Organization` model. * @param status - Status of the chat (ACTIVE, BLOCKED, DELETED). * @param createdAt - Timestamp of chat creation. * @param updatedAt - Timestamp of chat update. + * @param lastMessageId - ID of the last message in the chat. */ -const directChatSchema = new Schema( +const chatSchema = new Schema( { users: [ { @@ -37,10 +45,22 @@ const directChatSchema = new Schema( required: true, }, ], + isGroup: { + type: Boolean, + required: true, + }, + name: { + type: String, + required: false, + }, + image: { + type: String, + require: false, + }, messages: [ { type: Schema.Types.ObjectId, - ref: "DirectChatMessage", + ref: "ChatMessage", }, ], creatorId: { @@ -48,12 +68,36 @@ const directChatSchema = new Schema( ref: "User", required: true, }, + admins: [ + { + type: Schema.Types.ObjectId, + ref: "User", + required: false, + }, + ], status: { type: String, required: true, enum: ["ACTIVE", "BLOCKED", "DELETED"], default: "ACTIVE", }, + organization: { + type: Schema.Types.ObjectId, + ref: "Organization", + required: false, + }, + createdAt: { + type: Date, + required: true, + }, + updatedAt: { + type: Date, + required: true, + }, + lastMessageId: { + type: String, + required: false, + }, }, { timestamps: true, @@ -61,15 +105,16 @@ const directChatSchema = new Schema( ); // Add logging middleware for directChatSchema -createLoggingMiddleware(directChatSchema, "DirectChat"); +createLoggingMiddleware(chatSchema, "Chat"); /** * Retrieves or creates the Mongoose model for DirectChat. * Prevents Mongoose OverwriteModelError during testing. */ -const directChatModel = (): Model => - model("DirectChat", directChatSchema); +const chatModel = (): Model => + model("Chat", chatSchema); // This syntax is needed to prevent Mongoose OverwriteModelError while running tests. -export const DirectChat = (models.DirectChat || - directChatModel()) as ReturnType; +export const Chat = (models.Chat || chatModel()) as ReturnType< + typeof chatModel +>; diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts new file mode 100644 index 0000000000..1229935834 --- /dev/null +++ b/src/models/ChatMessage.ts @@ -0,0 +1,109 @@ +import type { PopulatedDoc, Types, Document, Model } from "mongoose"; +import { Schema, model, models } from "mongoose"; +import type { InterfaceUser } from "./User"; +import { createLoggingMiddleware } from "../libraries/dbLogger"; +import type { InterfaceChat } from "./Chat"; + +/** + * Represents a document for a chat message in the MongoDB database. + */ +export interface InterfaceChatMessage { + _id: Types.ObjectId; + chatMessageBelongsTo: PopulatedDoc; + sender: PopulatedDoc; + replyTo: PopulatedDoc; + messageContent: string; + status: string; + deletedBy: PopulatedDoc[]; + createdAt: Date; + updatedAt: Date; +} + +/** + * ChatMessage Schema + * + * This schema defines the structure of a chat message document in the database. + * + * Fields: + * - chatMessageBelongsTo: ObjectId, ref: "Chat", required + * - The chat to which this message belongs. + * - sender: ObjectId, ref: "User", required + * - The user who sent the message. + * - replyTo: ObjectId, ref: "ChatMessage", optional + * - The message to which this message is a reply. + * - messageContent: String, required + * - The content of the message. + * - type: String, required, enum: ["STRING", "VIDEO", "IMAGE", "FILE"] + * - The type of the message content. + * - status: String, required, enum: ["ACTIVE", "BLOCKED", "DELETED"], default: "ACTIVE" + * - The status of the message. + * - deletedBy: Array of ObjectId, ref: "User", optional + * - List of users who have deleted the message. + * - updatedAt: Date, required + * - The date when the message was last updated. + * - createdAt: Date, required + * - The date when the message was created. + * + * Options: + * - timestamps: Automatically adds createdAt and updatedAt fields. + */ +const chatMessageSchema = new Schema( + { + chatMessageBelongsTo: { + type: Schema.Types.ObjectId, + ref: "Chat", + required: true, + }, + sender: { + type: Schema.Types.ObjectId, + ref: "User", + required: true, + }, + replyTo: { + type: Schema.Types.ObjectId, + ref: "ChatMessage", + required: false, + }, + messageContent: { + type: String, + required: true, + }, + status: { + type: String, + required: true, + enum: ["ACTIVE", "BLOCKED", "DELETED"], + default: "ACTIVE", + }, + deletedBy: [ + { + type: Schema.Types.ObjectId, + ref: "User", + required: false, + }, + ], + updatedAt: { + type: Date, + required: true, + }, + createdAt: { + type: Date, + required: true, + }, + }, + { + timestamps: true, // Adds createdAt and updatedAt automatically + }, +); + +// Apply logging middleware to the schema +createLoggingMiddleware(chatMessageSchema, "DirectChatMessage"); + +/** + * Returns the Mongoose Model for DirectChatMessage to prevent OverwriteModelError. + */ +const chatMessageModel = (): Model => + model("ChatMessage", chatMessageSchema); + +// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. +export const ChatMessage = (models.ChatMessage || + chatMessageModel()) as ReturnType; diff --git a/src/models/DirectChatMessage.ts b/src/models/DirectChatMessage.ts deleted file mode 100644 index a31dcf809b..0000000000 --- a/src/models/DirectChatMessage.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { PopulatedDoc, Types, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceDirectChat } from "./DirectChat"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Represents a document for a direct chat message in the MongoDB database. - */ -export interface InterfaceDirectChatMessage { - _id: Types.ObjectId; - directChatMessageBelongsTo: PopulatedDoc; - sender: PopulatedDoc; - receiver: PopulatedDoc; - messageContent: string; - status: string; - createdAt: Date; - updatedAt: Date; -} - -/** - * Mongoose schema definition for a direct chat message document. - * @param directChatMessageBelongsTo - Reference to the direct chat session to which the message belongs. - * @param sender - Reference to the user who sent the message. - * @param receiver - Reference to the user who received the message. - * @param messageContent - Content of the direct chat message. - * @param status - Status of the message (ACTIVE, BLOCKED, DELETED). - * @param createdAt - Date when the direct chat message was created. - * @param updatedAt - Date when the direct chat message was last updated. - */ -const directChatMessageSchema = new Schema( - { - directChatMessageBelongsTo: { - type: Schema.Types.ObjectId, - ref: "DirectChat", - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - receiver: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - messageContent: { - type: String, - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], - default: "ACTIVE", - }, - }, - { - timestamps: true, // Adds createdAt and updatedAt automatically - }, -); - -// Apply logging middleware to the schema -createLoggingMiddleware(directChatMessageSchema, "DirectChatMessage"); - -/** - * Returns the Mongoose Model for DirectChatMessage to prevent OverwriteModelError. - */ -const directChatMessageModel = (): Model => - model( - "DirectChatMessage", - directChatMessageSchema, - ); - -// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. -export const DirectChatMessage = (models.DirectChatMessage || - directChatMessageModel()) as ReturnType; diff --git a/src/models/GroupChat.ts b/src/models/GroupChat.ts deleted file mode 100644 index 3ecf20f70d..0000000000 --- a/src/models/GroupChat.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { Types, PopulatedDoc, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceGroupChatMessage } from "./GroupChatMessage"; -import type { InterfaceOrganization } from "./Organization"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Interface representing a document for a group chat in the database (MongoDB). - */ -export interface InterfaceGroupChat { - _id: Types.ObjectId; - title: string; - users: PopulatedDoc[]; - messages: PopulatedDoc[]; - creatorId: PopulatedDoc; - createdAt: Date; - updatedAt: Date; - organization: PopulatedDoc; - status: string; -} -/** - * Mongoose schema definition for a group chat document. - * Defines how group chat data will be stored in MongoDB. - * - * @param title - Title of the group chat. - * @param users - Users participating in the group chat. - * @param messages - Messages sent in the group chat. - * @param creatorId - Creator of the group chat. - * @param createdAt - Timestamp of creation - * @param updatedAt - Timestamp of updation - * @param organization - Organization associated with the group chat. - * @param status - Status of the group chat. - */ -const groupChatSchema = new Schema( - { - title: { - type: String, - required: true, - }, - users: [ - { - type: Schema.Types.ObjectId, - ref: "User", - required: true, // At least one user is required - }, - ], - messages: [ - { - type: Schema.Types.ObjectId, - ref: "GroupChatMessage", - }, - ], - creatorId: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], // Status must be one of these values - default: "ACTIVE", - }, - }, - { - timestamps: true, // Automatically manage `createdAt` and `updatedAt` fields - }, -); - -/** - * Adds logging middleware to the group chat schema. - * Middleware logs changes to group chat documents. - */ -createLoggingMiddleware(groupChatSchema, "GroupChat"); - -/** - * Creates a Mongoose model for the group chat schema. - * Ensures that we don't create multiple models during testing, which can cause errors. - * - * @returns The GroupChat model. - */ -const groupChatModel = (): Model => - model("GroupChat", groupChatSchema); - -/** - * Export the GroupChat model. - * This syntax ensures we don't get an OverwriteModelError while running tests. - */ -export const GroupChat = (models.GroupChat || groupChatModel()) as ReturnType< - typeof groupChatModel ->; diff --git a/src/models/GroupChatMessage.ts b/src/models/GroupChatMessage.ts deleted file mode 100644 index f3b583bb2b..0000000000 --- a/src/models/GroupChatMessage.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { Types, PopulatedDoc, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceGroupChat } from "./GroupChat"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Interface representing a document for a group chat message in the database (MongoDB). - */ -export interface InterfaceGroupChatMessage { - _id: Types.ObjectId; - groupChatMessageBelongsTo: PopulatedDoc; - sender: PopulatedDoc; - createdAt: Date; - updatedAt: Date; - messageContent: string; - status: string; -} - -/** - * Mongoose schema for a group chat message. - * Defines the structure of the group chat message document stored in MongoDB. - * @param groupChatMessageBelongsTo - The association referring to the GroupChat model. - * @param sender - The sender of the message. - * @param messageContent - The content of the message. - * @param status - The status of the message (e.g., ACTIVE, BLOCKED, DELETED). - * @param createdAt - The date and time when the message was created. - * @param updatedAt - The date and time when the message was last updated. - */ -const groupChatMessageSchema = new Schema( - { - groupChatMessageBelongsTo: { - type: Schema.Types.ObjectId, - ref: "GroupChat", - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - messageContent: { - type: String, - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], - default: "ACTIVE", - }, - }, - { - timestamps: true, // Automatically adds `createdAt` and `updatedAt` fields - }, -); - -// Add logging middleware for groupChatMessageSchema -createLoggingMiddleware(groupChatMessageSchema, "GroupChatMessage"); - -/** - * Function to retrieve or create the Mongoose model for the GroupChatMessage. - * This is necessary to avoid the OverwriteModelError during testing. - * @returns The Mongoose model for the GroupChatMessage. - */ -const groupChatMessageModel = (): Model => - model("GroupChatMessage", groupChatMessageSchema); - -/** - * The Mongoose model for the GroupChatMessage. - * If the model already exists (e.g., during testing), it uses the existing model. - * Otherwise, it creates a new model. - */ -export const GroupChatMessage = (models.GroupChatMessage || - groupChatMessageModel()) as ReturnType; diff --git a/src/models/index.ts b/src/models/index.ts index 9ce9aed7e7..6c88b18db6 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -9,8 +9,6 @@ export * from "./CheckIn"; export * from "./CheckOut"; export * from "./Comment"; export * from "./Community"; -export * from "./DirectChat"; -export * from "./DirectChatMessage"; export * from "./Donation"; export * from "./Event"; export * from "./EventAttendee"; @@ -21,8 +19,6 @@ export * from "./File"; export * from "./Fund"; export * from "./FundraisingCampaign"; export * from "./Group"; -export * from "./GroupChat"; -export * from "./GroupChatMessage"; export * from "./ImageHash"; export * from "./Language"; export * from "./MembershipRequest"; @@ -40,3 +36,5 @@ export * from "./TagUser"; export * from "./Venue"; export * from "./User"; export * from "./Note"; +export * from "./Chat"; +export * from "./ChatMessage"; diff --git a/src/resolvers/Chat/admins.ts b/src/resolvers/Chat/admins.ts new file mode 100644 index 0000000000..a1028aa4e2 --- /dev/null +++ b/src/resolvers/Chat/admins.ts @@ -0,0 +1,14 @@ +import { User } from "../../models"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the list of all chat admins from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the list of users. + */ +export const admins: ChatResolvers["users"] = async (parent) => { + return await User.find({ + _id: { + $in: parent.users, + }, + }).lean(); +}; diff --git a/src/resolvers/DirectChat/creator.ts b/src/resolvers/Chat/creator.ts similarity index 51% rename from src/resolvers/DirectChat/creator.ts rename to src/resolvers/Chat/creator.ts index 02fed5c4a9..8d76e1ec3b 100644 --- a/src/resolvers/DirectChat/creator.ts +++ b/src/resolvers/Chat/creator.ts @@ -1,11 +1,11 @@ import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the specified Direct Chat User from database. + * This resolver function will fetch and return the specified Chat User from database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains the User data. */ -export const creator: DirectChatResolvers["creator"] = async (parent) => { +export const creator: ChatResolvers["creator"] = async (parent) => { return await User.findOne({ _id: parent.creatorId, }).lean(); diff --git a/src/resolvers/GroupChat/index.ts b/src/resolvers/Chat/index.ts similarity index 57% rename from src/resolvers/GroupChat/index.ts rename to src/resolvers/Chat/index.ts index 9c81560015..d4559ae213 100644 --- a/src/resolvers/GroupChat/index.ts +++ b/src/resolvers/Chat/index.ts @@ -1,12 +1,14 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; import { creator } from "./creator"; import { messages } from "./messages"; import { organization } from "./organization"; import { users } from "./users"; +import { admins } from "./admins"; -export const GroupChat: GroupChatResolvers = { +export const Chat: ChatResolvers = { creator, messages, organization, users, + admins, }; diff --git a/src/resolvers/Chat/messages.ts b/src/resolvers/Chat/messages.ts new file mode 100644 index 0000000000..db16a74708 --- /dev/null +++ b/src/resolvers/Chat/messages.ts @@ -0,0 +1,14 @@ +import { ChatMessage } from "../../models"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the list of all messages in specified Chat from database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the list of messages. + */ +export const messages: ChatResolvers["messages"] = async (parent) => { + return await ChatMessage.find({ + _id: { + $in: parent.messages, + }, + }).lean(); +}; diff --git a/src/resolvers/DirectChat/organization.ts b/src/resolvers/Chat/organization.ts similarity index 82% rename from src/resolvers/DirectChat/organization.ts rename to src/resolvers/Chat/organization.ts index 9073af15f4..b5692d9392 100644 --- a/src/resolvers/DirectChat/organization.ts +++ b/src/resolvers/Chat/organization.ts @@ -2,15 +2,13 @@ import type { InterfaceOrganization } from "../../models"; import { Organization } from "../../models"; import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the Organization for the Direct Chat from database. + * This resolver function will fetch and return the Organization for the Chat from database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains Organization data. */ -export const organization: DirectChatResolvers["organization"] = async ( - parent, -) => { +export const organization: ChatResolvers["organization"] = async (parent) => { const organizationFoundInCache = await findOrganizationsInCache([ parent.organization, ]); diff --git a/src/resolvers/DirectChat/users.ts b/src/resolvers/Chat/users.ts similarity index 65% rename from src/resolvers/DirectChat/users.ts rename to src/resolvers/Chat/users.ts index ebb3893c7f..3912780779 100644 --- a/src/resolvers/DirectChat/users.ts +++ b/src/resolvers/Chat/users.ts @@ -1,11 +1,11 @@ import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the list of all direct chat users from the database. + * This resolver function will fetch and return the list of all chat users from the database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains the list of users. */ -export const users: DirectChatResolvers["users"] = async (parent) => { +export const users: ChatResolvers["users"] = async (parent) => { return await User.find({ _id: { $in: parent.users, diff --git a/src/resolvers/ChatMessage/chatMessageBelongsTo.ts b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts new file mode 100644 index 0000000000..bdd5277b6b --- /dev/null +++ b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts @@ -0,0 +1,25 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; +import { CHAT_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver method will retrieve and return from the database the Chat to which the specified message belongs. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the Chat data. + */ +export const chatMessageBelongsTo: ChatMessageResolvers["chatMessageBelongsTo"] = + async (parent) => { + const chatResult = await Chat.findOne({ + _id: parent.chatMessageBelongsTo, + }).lean(); + + if (chatResult) { + return chatResult; + } else { + throw new errors.NotFoundError( + requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + }; diff --git a/src/resolvers/ChatMessage/index.ts b/src/resolvers/ChatMessage/index.ts new file mode 100644 index 0000000000..3b1d0e60f0 --- /dev/null +++ b/src/resolvers/ChatMessage/index.ts @@ -0,0 +1,10 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { chatMessageBelongsTo } from "./chatMessageBelongsTo"; +import { replyTo } from "./replyTo"; +import { sender } from "./sender"; + +export const ChatMessage: ChatMessageResolvers = { + chatMessageBelongsTo, + sender, + replyTo, +}; diff --git a/src/resolvers/ChatMessage/replyTo.ts b/src/resolvers/ChatMessage/replyTo.ts new file mode 100644 index 0000000000..ff2dc872bb --- /dev/null +++ b/src/resolvers/ChatMessage/replyTo.ts @@ -0,0 +1,28 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { ChatMessage } from "../../models"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the message replied to specific to the chat from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains reply Message's data. + */ +export const replyTo: ChatMessageResolvers["replyTo"] = async (parent) => { + if (parent.replyTo) { + const result = await ChatMessage.findOne({ + _id: parent.replyTo, + }).lean(); + + if (result) { + return result; + } else { + throw new errors.NotFoundError( + requestContext.translate(MESSAGE_NOT_FOUND_ERROR.MESSAGE), + MESSAGE_NOT_FOUND_ERROR.CODE, + MESSAGE_NOT_FOUND_ERROR.PARAM, + ); + } + } else { + return null; + } +}; diff --git a/src/resolvers/ChatMessage/sender.ts b/src/resolvers/ChatMessage/sender.ts new file mode 100644 index 0000000000..c318fdd7ae --- /dev/null +++ b/src/resolvers/ChatMessage/sender.ts @@ -0,0 +1,24 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { User } from "../../models"; +import { USER_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the sender(user) of the Chat from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains User's data. + */ +export const sender: ChatMessageResolvers["sender"] = async (parent) => { + const result = await User.findOne({ + _id: parent.sender, + }).lean(); + + if (result) { + return result; + } else { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } +}; diff --git a/src/resolvers/DirectChat/index.ts b/src/resolvers/DirectChat/index.ts deleted file mode 100644 index 8a0f6a4059..0000000000 --- a/src/resolvers/DirectChat/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -import { creator } from "./creator"; -import { messages } from "./messages"; -import { organization } from "./organization"; -import { users } from "./users"; - -/** - * Resolver function for the `DirectChat` type. - * - * This resolver is used to resolve the fields of a `DirectChat` type. - * - * @see users - The resolver function for the `users` field of a `DirectChat`. - * @see organization - The resolver function for the `organization` field of a `DirectChat`. - * @see messages - The resolver function for the `messages` field of a `DirectChat`. - * @see creator - The resolver function for the `creator` field of a `DirectChat`. - * @see DirectChatResolvers - The type definition for the resolvers of the DirectChat fields. - * - */ -export const DirectChat: DirectChatResolvers = { - creator, - messages, - organization, - users, -}; diff --git a/src/resolvers/DirectChat/messages.ts b/src/resolvers/DirectChat/messages.ts deleted file mode 100644 index 3a3332ff88..0000000000 --- a/src/resolvers/DirectChat/messages.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DirectChatMessage } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -/** - * This resolver function will fetch and return the list of all messages in specified Direct Chat from database. - * @param parent - An object that is the return value of the resolver for this field's parent. - * @returns An `object` that contains the list of messages. - */ -export const messages: DirectChatResolvers["messages"] = async (parent) => { - return await DirectChatMessage.find({ - _id: { - $in: parent.messages, - }, - }).lean(); -}; diff --git a/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts b/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts deleted file mode 100644 index eb6a0d4d32..0000000000 --- a/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { DirectChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `directChatMessageBelongsTo` field of a `DirectChatMessage`. - * - * This function retrieves the direct chat to which a specific direct chat message belongs. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the direct chat to which it belongs. - * @returns A promise that resolves to the direct chat document found in the database. This document represents the direct chat to which the direct chat message belongs. - * - * @see DirectChat - The DirectChat model used to interact with the direct chats collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const directChatMessageBelongsTo: DirectChatMessageResolvers["directChatMessageBelongsTo"] = - async (parent) => { - const directChatResult = await DirectChat.findOne({ - _id: parent.directChatMessageBelongsTo, - }).lean(); - - if (directChatResult) { - return directChatResult; - } else { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - }; diff --git a/src/resolvers/DirectChatMessage/index.ts b/src/resolvers/DirectChatMessage/index.ts deleted file mode 100644 index e42390c4ec..0000000000 --- a/src/resolvers/DirectChatMessage/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { directChatMessageBelongsTo } from "./directChatMessageBelongsTo"; -import { receiver } from "./receiver"; -import { sender } from "./sender"; - -export const DirectChatMessage: DirectChatMessageResolvers = { - directChatMessageBelongsTo, - receiver, - sender, -}; diff --git a/src/resolvers/DirectChatMessage/receiver.ts b/src/resolvers/DirectChatMessage/receiver.ts deleted file mode 100644 index 1702f33b66..0000000000 --- a/src/resolvers/DirectChatMessage/receiver.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `receiver` field of a `DirectChatMessage`. - * - * This function retrieves the user who received a specific direct chat message. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the user who received it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who received the direct chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const receiver: DirectChatMessageResolvers["receiver"] = async ( - parent, -) => { - const result = await User.findOne({ - _id: parent.receiver, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/DirectChatMessage/sender.ts b/src/resolvers/DirectChatMessage/sender.ts deleted file mode 100644 index 9a20bb4490..0000000000 --- a/src/resolvers/DirectChatMessage/sender.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `sender` field of a `DirectChatMessage`. - * - * This function retrieves the user who sent a specific direct chat message. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the user who sent it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who sent the direct chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const sender: DirectChatMessageResolvers["sender"] = async (parent) => { - const result = await User.findOne({ - _id: parent.sender, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/GroupChat/creator.ts b/src/resolvers/GroupChat/creator.ts deleted file mode 100644 index ff7ea2cd51..0000000000 --- a/src/resolvers/GroupChat/creator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; - -/** - * Resolver function for the `creator` field of a `GroupChat`. - * - * This function retrieves the user who created a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the ID of the user who created it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who created the group chat. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const creator: GroupChatResolvers["creator"] = async (parent) => { - return await User.findOne({ - _id: parent.creatorId, - }).lean(); -}; diff --git a/src/resolvers/GroupChat/messages.ts b/src/resolvers/GroupChat/messages.ts deleted file mode 100644 index cb03954b94..0000000000 --- a/src/resolvers/GroupChat/messages.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChatMessage } from "../../models"; - -/** - * Resolver function for the `messages` field of a `GroupChat`. - * - * This function retrieves the messages associated with a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the IDs of the messages associated with it. - * @returns A promise that resolves to the message documents found in the database. These documents represent the messages associated with the group chat. - * - * @see GroupChatMessage - The GroupChatMessage model used to interact with the group chat messages collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const messages: GroupChatResolvers["messages"] = async (parent) => { - return await GroupChatMessage.find({ - _id: { - $in: parent.messages, - }, - }).lean(); -}; diff --git a/src/resolvers/GroupChat/organization.ts b/src/resolvers/GroupChat/organization.ts deleted file mode 100644 index ab83f0f3b3..0000000000 --- a/src/resolvers/GroupChat/organization.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { Organization } from "../../models"; -import type { InterfaceOrganization } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; - -/** - * Resolver function for the `organization` field of a `GroupChat`. - * - * This function retrieves the organization associated with a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the ID of the organization it is associated with. - * @returns A promise that resolves to the organization document found in the database. This document represents the organization associated with the group chat. - * - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const organization: GroupChatResolvers["organization"] = async ( - parent, -) => { - const organizationFoundInCache = await findOrganizationsInCache([ - parent.organization, - ]); - - if (!organizationFoundInCache.includes(null)) { - return organizationFoundInCache[0] as InterfaceOrganization; - } - - const organization = await Organization.findOne({ - _id: parent.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - - return organization as InterfaceOrganization; -}; diff --git a/src/resolvers/GroupChat/users.ts b/src/resolvers/GroupChat/users.ts deleted file mode 100644 index b4e0f363e1..0000000000 --- a/src/resolvers/GroupChat/users.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; - -/** - * Resolver function for the `users` field of a `GroupChat`. - * - * This function retrieves the users who are members of a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the IDs of the users who are members of it. - * @returns A promise that resolves to the user documents found in the database. These documents represent the users who are members of the group chat. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const users: GroupChatResolvers["users"] = async (parent) => { - return await User.find({ - _id: { - $in: parent.users, - }, - }).lean(); -}; diff --git a/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts b/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts deleted file mode 100644 index c9e2ec6a08..0000000000 --- a/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChat } from "../../models"; -import { errors, requestContext } from "../../libraries"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * Resolver function for the `groupChatMessageBelongsTo` field of a `GroupChatMessage`. - * - * This function retrieves the group chat to which a specific group chat message belongs. - * - * @param parent - The parent object representing the group chat message. It contains information about the group chat message, including the ID of the group chat to which it belongs. - * @returns A promise that resolves to the group chat document found in the database. This document represents the group chat to which the group chat message belongs. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see GroupChatMessageResolvers - The type definition for the resolvers of the GroupChatMessage fields. - * - */ -export const groupChatMessageBelongsTo: GroupChatMessageResolvers["groupChatMessageBelongsTo"] = - async (parent) => { - const result = await GroupChat.findOne({ - _id: parent.groupChatMessageBelongsTo, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - }; diff --git a/src/resolvers/GroupChatMessage/index.ts b/src/resolvers/GroupChatMessage/index.ts deleted file mode 100644 index b837e04871..0000000000 --- a/src/resolvers/GroupChatMessage/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { groupChatMessageBelongsTo } from "./groupChatMessageBelongsTo"; -import { sender } from "./sender"; - -export const GroupChatMessage: GroupChatMessageResolvers = { - groupChatMessageBelongsTo, - sender, -}; diff --git a/src/resolvers/GroupChatMessage/sender.ts b/src/resolvers/GroupChatMessage/sender.ts deleted file mode 100644 index 9497a05f23..0000000000 --- a/src/resolvers/GroupChatMessage/sender.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `sender` field of a `GroupChatMessage`. - * - * This function retrieves the user who sent a specific group chat message. - * - * @param parent - The parent object representing the group chat message. It contains information about the group chat message, including the ID of the user who sent it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who sent the group chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatMessageResolvers - The type definition for the resolvers of the GroupChatMessage fields. - * - */ -export const sender: GroupChatMessageResolvers["sender"] = async (parent) => { - const result = await User.findOne({ - _id: parent.sender, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/Mutation/addUserToGroupChat.ts b/src/resolvers/Mutation/addUserToGroupChat.ts deleted file mode 100644 index d71535f578..0000000000 --- a/src/resolvers/Mutation/addUserToGroupChat.ts +++ /dev/null @@ -1,127 +0,0 @@ -import "dotenv/config"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_ALREADY_MEMBER_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { adminCheck } from "../../utilities"; -import type { InterfaceGroupChat } from "../../models"; - -/** - * Mutation resolver function to add a user to a group chat. - * - * This function performs the following actions: - * 1. Checks if the group chat specified by `args.chatId` exists. - * 2. Checks if the organization associated with the group chat exists. - * 3. Verifies that the current user (identified by `context.userId`) is an admin of the organization. - * 4. Confirms that the user to be added (specified by `args.userId`) exists. - * 5. Ensures that the user is not already a member of the group chat. - * 6. Adds the user to the list of users in the group chat and returns the updated group chat. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `chatId`: The ID of the group chat to which the user will be added. - * - `userId`: The ID of the user to be added to the group chat. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user making the request. - * - * @returns A promise that resolves to the updated group chat document with the new user added. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see User - The User model used to interact with the users collection in the database. - * @see MutationResolvers - The type definition for the mutation resolvers. - * @see adminCheck - Utility function to check if the current user is an admin of the organization. - * @see findOrganizationsInCache - Service function to retrieve organizations from cache. - * @see cacheOrganizations - Service function to cache updated organization data. - */ -export const addUserToGroupChat: MutationResolvers["addUserToGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) { - await cacheOrganizations([organization]); - } - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organization. - await adminCheck(context.userId, organization); - - const userExists = !!(await User.exists({ - _id: args.userId, - })); - - // Checks whether user with _id === args.userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - const isUserGroupChatMember = groupChat.users.some((user) => - user.equals(args.userId), - ); - - // Checks whether user with _id === args.userId is already a member of groupChat. - if (isUserGroupChatMember === true) { - throw new errors.ConflictError( - requestContext.translate(USER_ALREADY_MEMBER_ERROR.MESSAGE), - USER_ALREADY_MEMBER_ERROR.CODE, - USER_ALREADY_MEMBER_ERROR.PARAM, - ); - } - - // Adds args.userId to users list on groupChat's document and returns the updated groupChat. - return (await GroupChat.findOneAndUpdate( - { - _id: args.chatId, - }, - { - $push: { - users: args.userId, - }, - }, - { - new: true, - }, - ).lean()) as InterfaceGroupChat; - }; diff --git a/src/resolvers/Mutation/adminRemoveGroup.ts b/src/resolvers/Mutation/adminRemoveGroup.ts deleted file mode 100644 index 972f6bca06..0000000000 --- a/src/resolvers/Mutation/adminRemoveGroup.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { AppUserProfile, GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { adminCheck } from "../../utilities"; - -/** - * Mutation resolver function to remove a group chat. - * - * This function performs the following actions: - * 1. Checks if the group chat specified by `args.groupId` exists. - * 2. Verifies that the organization associated with the group chat exists. - * 3. Ensures that the current user (identified by `context.userId`) exists. - * 4. Checks that the current user is authorized as an admin of the organization. - * 5. Deletes the group chat from the database. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `groupId`: The ID of the group chat to be removed. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user making the request. - * - * @returns A promise that resolves to the deleted group chat document. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see User - The User model used to interact with the users collection in the database. - * @see AppUserProfile - The AppUserProfile model used to retrieve the user's profile information. - * @see MutationResolvers - The type definition for the mutation resolvers. - * @see adminCheck - Utility function to check if the current user is an admin of the organization. - * @see findOrganizationsInCache - Service function to retrieve organizations from cache. - * @see cacheOrganizations - Service function to cache updated organization data. - */ -export const adminRemoveGroup: MutationResolvers["adminRemoveGroup"] = async ( - _parent, - args, - context, -) => { - const groupChat = await GroupChat.findOne({ - _id: args.groupId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) { - await cacheOrganizations([organization]); - } - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - // Checks currentUser with _id === context.userId exists. - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const currentUserAppProfile = await AppUserProfile.findOne({ - userId: context.userId, - }).lean(); - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organization. - await adminCheck(context.userId, organization); - - //remove message from organization - // org.overwrite({ - // ...org._doc, - // messages: org._doc.posts.filter((message) => message != args.messageId), - // }); - // await org.save(); - - // //remove post from user - // user.overwrite({ - // ...user._doc, - // messages: user._doc.posts.filter((message) => message != args.messageId), - // }); - // await user.save(); - - // Deletes the groupChat. - await GroupChat.deleteOne({ - _id: groupChat._id, - }); - - // Returns the deleted groupChat. - return groupChat; -}; diff --git a/src/resolvers/Mutation/createChat.ts b/src/resolvers/Mutation/createChat.ts new file mode 100644 index 0000000000..650707cb44 --- /dev/null +++ b/src/resolvers/Mutation/createChat.ts @@ -0,0 +1,80 @@ +import { + ORGANIZATION_NOT_FOUND_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import { Chat, Organization, User } from "../../models"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This function enables to create a chat. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the user exists + * 2. If the organization exists + * @returns Created chat + */ +export const createChat: MutationResolvers["createChat"] = async ( + _parent, + args, + context, +) => { + let organization; + if (args.data.isGroup && args.data.organizationId) { + organization = await Organization.findOne({ + _id: args.data.organizationId, + }); + + // Checks whether organization with _id === args.data.organizationId exists. + if (!organization) { + throw new errors.NotFoundError( + requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), + ORGANIZATION_NOT_FOUND_ERROR.CODE, + ORGANIZATION_NOT_FOUND_ERROR.PARAM, + ); + } + } + + // const userExists = (await User.exists({ + // _id: { $in: args.data.userIds }, + // })) as unknown as string[]; + + const userExists = await User.find({ + _id: { $in: args.data.userIds }, + }).lean(); + + if (userExists && userExists.length !== args.data.userIds.length) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + const now = new Date(); + + const chatPayload = args.data.isGroup + ? { + isGroup: args.data.isGroup, + creatorId: context.userId, + users: args.data.userIds, + organization: args.data.organizationId, + name: args.data?.name, + admins: [context.userId], + createdAt: now, + updatedAt: now, + image: args.data.image, + } + : { + creatorId: context.userId, + users: args.data.userIds, + isGroup: args.data.isGroup, + createdAt: now, + updatedAt: now, + }; + + const createdChat = await Chat.create(chatPayload); + + return createdChat; +}; diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts deleted file mode 100644 index 85d352638a..0000000000 --- a/src/resolvers/Mutation/createDirectChat.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { User, DirectChat } from "../../models"; -import { errors, requestContext } from "../../libraries"; - -import { USER_NOT_FOUND_ERROR } from "../../constants"; - -/** - * Creates a new direct chat and associates it with an organization. - * - * This resolver performs the following steps: - * - * 1. Retrieves the organization based on the provided `organizationId`. - * 2. Checks if the organization exists, either from cache or database. - * 3. Validates that all user IDs provided in `userIds` exist. - * 4. Creates a new direct chat with the specified users and organization. - * - * @param _parent - The parent object, not used in this resolver. - * @param args - The input arguments for the mutation, including: - * - `data`: An object containing: - * - `organizationId`: The ID of the organization to associate with the direct chat. - * - `userIds`: An array of user IDs to be included in the direct chat. - * @param context - The context object containing user information (context.userId). - * - * @returns A promise that resolves to the created direct chat object. - * - * @remarks This function includes caching operations to optimize data retrieval and ensures that all user IDs are valid before creating the direct chat. - */ -export const createDirectChat: MutationResolvers["createDirectChat"] = async ( - _parent, - args, - context, -) => { - // Variable to store list of users to be members of directChat. - const usersInDirectChat = []; - - // Loops over each item in args.data.userIds list. - for await (const userId of args.data.userIds) { - const userExists = !!(await User.exists({ - _id: userId, - })); - - // Checks whether user with _id === userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - usersInDirectChat.push(userId); - } - - // Creates new directChat. - const createdDirectChat = await DirectChat.create({ - creatorId: context.userId, - users: usersInDirectChat, - }); - - // Returns createdDirectChat. - return createdDirectChat.toObject(); -}; diff --git a/src/resolvers/Mutation/createGroupChat.ts b/src/resolvers/Mutation/createGroupChat.ts deleted file mode 100644 index 17dc1548b0..0000000000 --- a/src/resolvers/Mutation/createGroupChat.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Creates a new group chat and associates it with a specified organization. - * - * This resolver performs the following actions: - * - * 1. Checks if the specified organization exists in the cache, and if not, fetches it from the database and caches it. - * 2. Verifies that the organization with the given ID exists. - * 3. Checks if each user specified in the `userIds` list exists. - * 4. Creates a new group chat with the specified users, organization, and title. - * - * @param _parent - The parent object, not used in this resolver. - * @param args - The input arguments for the mutation, including: - * - `data`: An object containing: - * - `organizationId`: The ID of the organization to associate with the group chat. - * - `userIds`: A list of user IDs to be added to the group chat. - * - `title`: The title of the group chat. - * @param context - The context object containing user information (context.userId). - * - * @returns A promise that resolves to the created group chat object. - * - * @remarks This function ensures the existence of the organization and users, and caches the organization if it is not already cached. It returns the created group chat object. - */ -export const createGroupChat: MutationResolvers["createGroupChat"] = async ( - _parent, - args, - context, -) => { - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - args.data.organizationId, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: args.data.organizationId, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether the organization with _id === args.data.organizationId exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Variable to store list of users to be members of group chat. - const usersInGroupChat = []; - - // Loops over each item in args.data.userIds list. - for await (const userId of args.data.userIds) { - const userExists = !!(await User.exists({ - _id: userId, - })); - - // Checks whether user with _id === userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - usersInGroupChat.push(userId); - } - - // Creates new group chat. - const createdGroupChat = await GroupChat.create({ - creatorId: context.userId, - users: usersInGroupChat, - organization: args.data?.organizationId, - title: args.data?.title, - }); - - // Returns created group chat. - return createdGroupChat.toObject(); -}; diff --git a/src/resolvers/Mutation/createMessageChat.ts b/src/resolvers/Mutation/createMessageChat.ts deleted file mode 100644 index e7d6fdab4c..0000000000 --- a/src/resolvers/Mutation/createMessageChat.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import type { InterfaceAppUserProfile, InterfaceUser } from "../../models"; -import { AppUserProfile, MessageChat, User } from "../../models"; -import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; -import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Creates a new chat message between users. - * - * This function performs the following actions: - * 1. Verifies the existence of the current user. - * 2. Retrieves and caches the current user's details and application profile if not already cached. - * 3. Checks the existence of the receiver user and retrieves their application profile. - * 4. Ensures that both the current user and the receiver have valid application profiles. - * 5. Compares the language codes of the sender and receiver to determine if there is a language barrier. - * 6. Creates a new chat message with the specified content and language barrier status. - * 7. Publishes the created message chat to a pub/sub channel for real-time updates. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `data.receiver`: The ID of the user receiving the message. - * - `data.message`: The content of the message being sent. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user sending the message. - * - `pubsub`: The pub/sub instance for publishing real-time updates. - * - * @returns The created message chat record. - * - */ -export const createMessageChat: MutationResolvers["createMessageChat"] = async ( - _parent, - args, - context, -) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - if (!currentUser) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - let currentUserAppProfile: InterfaceAppUserProfile | null; - const appUserProfileFoundInCache = await findAppUserProfileCache([ - currentUser.appUserProfileId?.toString(), - ]); - currentUserAppProfile = appUserProfileFoundInCache[0]; - if (currentUserAppProfile === null) { - currentUserAppProfile = await AppUserProfile.findOne({ - userId: currentUser._id, - }).lean(); - if (currentUserAppProfile !== null) { - await cacheAppUserProfile([currentUserAppProfile]); - } - } - - const receiverUser = await User.findOne({ - _id: args.data.receiver, - }).lean(); - - // Checks whether receiverUser exists. - if (!receiverUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const receiverUserAppProfile = await AppUserProfile.findOne({ - userId: receiverUser._id, - }).lean(); - if (!receiverUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Boolean to identify whether both sender and receiver for messageChat have the same appLanguageCode. - const isSenderReceiverLanguageSame = - receiverUserAppProfile?.appLanguageCode === - currentUserAppProfile?.appLanguageCode; - - // Creates new messageChat. - const createdMessageChat = await MessageChat.create({ - sender: currentUser?._id, - receiver: receiverUser._id, - message: args.data.message, - languageBarrier: !isSenderReceiverLanguageSame, - }); - - context.pubsub.publish("CHAT_CHANNEL", { - directMessageChat: { - ...createdMessageChat, - }, - }); - - // Returns createdMessageChat. - return createdMessageChat.toObject(); -}; diff --git a/src/resolvers/Mutation/index.ts b/src/resolvers/Mutation/index.ts index 353670e350..d4325f62cf 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -7,9 +7,7 @@ import { addOrganizationCustomField } from "./addOrganizationCustomField"; import { addOrganizationImage } from "./addOrganizationImage"; import { addUserCustomData } from "./addUserCustomData"; import { addUserImage } from "./addUserImage"; -import { addUserToGroupChat } from "./addUserToGroupChat"; import { addUserToUserFamily } from "./addUserToUserFamily"; -import { adminRemoveGroup } from "./adminRemoveGroup"; import { assignUserTag } from "./assignUserTag"; import { blockPluginCreationBySuperadmin } from "./blockPluginCreationBySuperadmin"; import { blockUser } from "./blockUser"; @@ -24,7 +22,7 @@ import { createAgendaCategory } from "./createAgendaCategory"; import { createAgendaItem } from "./createAgendaItem"; import { createAgendaSection } from "./createAgendaSection"; import { createComment } from "./createComment"; -import { createDirectChat } from "./createDirectChat"; +import { createChat } from "./createChat"; import { createDonation } from "./createDonation"; import { createEvent } from "./createEvent"; import { createEventVolunteer } from "./createEventVolunteer"; @@ -32,9 +30,7 @@ import { createFund } from "./createFund"; import { createFundraisingCampaign } from "./createFundraisingCampaign"; import { createEventVolunteerGroup } from "./createEventVolunteerGroup"; import { createFundraisingCampaignPledge } from "./createFundraisingCampaignPledge"; -import { createGroupChat } from "./createGroupChat"; import { createMember } from "./createMember"; -import { createMessageChat } from "./createMessageChat"; import { createOrganization } from "./createOrganization"; import { createPlugin } from "./createPlugin"; import { createPost } from "./createPost"; @@ -65,13 +61,11 @@ import { removeAdmin } from "./removeAdmin"; import { removeAgendaItem } from "./removeAgendaItem"; import removeAgendaSection from "./removeAgendaSection"; import { removeComment } from "./removeComment"; -import { removeDirectChat } from "./removeDirectChat"; import { removeEvent } from "./removeEvent"; import { removeEventAttendee } from "./removeEventAttendee"; import { removeEventVolunteer } from "./removeEventVolunteer"; import { removeEventVolunteerGroup } from "./removeEventVolunteerGroup"; import { removeFundraisingCampaignPledge } from "./removeFundraisingCampaingPledge"; -import { removeGroupChat } from "./removeGroupChat"; import { removeMember } from "./removeMember"; import { removeOrganization } from "./removeOrganization"; import { removeOrganizationCustomField } from "./removeOrganizationCustomField"; @@ -80,7 +74,6 @@ import { removePost } from "./removePost"; import { removeSampleOrganization } from "./removeSampleOrganization"; import { removeUserCustomData } from "./removeUserCustomData"; import { removeUserFamily } from "./removeUserFamily"; -import { removeUserFromGroupChat } from "./removeUserFromGroupChat"; import { removeUserFromUserFamily } from "./removeUserFromUserFamily"; import { removeUserImage } from "./removeUserImage"; import { removeUserTag } from "./removeUserTag"; @@ -88,8 +81,7 @@ import { resetCommunity } from "./resetCommunity"; import { revokeRefreshTokenForUser } from "./revokeRefreshTokenForUser"; import { saveFcmToken } from "./saveFcmToken"; import { sendMembershipRequest } from "./sendMembershipRequest"; -import { sendMessageToDirectChat } from "./sendMessageToDirectChat"; -import { sendMessageToGroupChat } from "./sendMessageToGroupChat"; +import { sendMessageToChat } from "./sendMessageToChat"; import { signUp } from "./signUp"; import { togglePostPin } from "./togglePostPin"; import { unassignUserTag } from "./unassignUserTag"; @@ -132,8 +124,6 @@ export const Mutation: MutationResolvers = { addOrganizationImage, addUserCustomData, addUserImage, - addUserToGroupChat, - adminRemoveGroup, addUserToUserFamily, removeUserFamily, removeUserFromUserFamily, @@ -153,13 +143,11 @@ export const Mutation: MutationResolvers = { createAgendaCategory, createAgendaItem, createAgendaSection, - createDirectChat, + createChat, createDonation, createEvent, createFund, createFundraisingCampaign, - createGroupChat, - createMessageChat, createOrganization, createNote, createPlugin, @@ -194,12 +182,10 @@ export const Mutation: MutationResolvers = { removeAgendaItem, removeAgendaSection, removeComment, - removeDirectChat, removeEvent, removeEventAttendee, removeEventVolunteer, removeEventVolunteerGroup, - removeGroupChat, removeMember, removeOrganization, removeOrganizationCustomField, @@ -207,15 +193,13 @@ export const Mutation: MutationResolvers = { removeSampleOrganization, removePost, removeUserCustomData, - removeUserFromGroupChat, removeUserImage, removeUserTag, resetCommunity, revokeRefreshTokenForUser, saveFcmToken, sendMembershipRequest, - sendMessageToDirectChat, - sendMessageToGroupChat, + sendMessageToChat, signUp, togglePostPin, unassignUserTag, diff --git a/src/resolvers/Mutation/removeDirectChat.ts b/src/resolvers/Mutation/removeDirectChat.ts deleted file mode 100644 index eb1abbe891..0000000000 --- a/src/resolvers/Mutation/removeDirectChat.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { DirectChat, DirectChatMessage, Organization } from "../../models"; -import { adminCheck } from "../../utilities"; -import { errors, requestContext } from "../../libraries"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, -} from "../../constants"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -/** - * This function enables to remove direct chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the organization exists - * 2. If the chat exists - * 3. If the user is an admin of the organization. - * @returns Deleted chat. - */ -export const removeDirectChat: MutationResolvers["removeDirectChat"] = async ( - _parent, - args, - context, -) => { - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - args.organizationId, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: args.organizationId, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - const directChat = await DirectChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether directChat exists. - if (!directChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organzation. - await adminCheck(context.userId, organization); - - // Deletes all directChatMessages with _id as one of the ids in directChat.messages list. - await DirectChatMessage.deleteMany({ - _id: { - $in: directChat.messages, - }, - }); - - // Deletes the directChat. - await DirectChat.deleteOne({ - _id: args.chatId, - }); - - // Returns deleted directChat. - return directChat; -}; diff --git a/src/resolvers/Mutation/removeGroupChat.ts b/src/resolvers/Mutation/removeGroupChat.ts deleted file mode 100644 index 7509d3fa20..0000000000 --- a/src/resolvers/Mutation/removeGroupChat.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { adminCheck } from "../../utilities"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, -} from "../../constants"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, GroupChatMessage, Organization } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -/** - * This function enables to remove an graoup chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists - * 2. If the organization exists - * 3. If the user is an admin of the organization. - * @returns Deleted group chat. - */ -export const removeGroupChat: MutationResolvers["removeGroupChat"] = async ( - _parent, - args, - context, -) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks if a groupChat with _id === args.chatId exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks if an organization with _id === groupChat.organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether current user making the request is an admin of organization. - await adminCheck(context.userId, organization); - - // Delete all groupChatMessages that have their ids stored in messages list of groupChat - await GroupChatMessage.deleteMany({ - _id: { - $in: groupChat.messages, - }, - }); - - // Delete the groupChat - await GroupChat.deleteOne({ - _id: groupChat._id, - }); - - return groupChat; -}; diff --git a/src/resolvers/Mutation/removeUserFromGroupChat.ts b/src/resolvers/Mutation/removeUserFromGroupChat.ts deleted file mode 100644 index fea9d35e00..0000000000 --- a/src/resolvers/Mutation/removeUserFromGroupChat.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, -} from "../../constants"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization } from "../../models"; -import { adminCheck } from "../../utilities"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { InterfaceGroupChat } from "../../models"; -/** - * This function enables to remove a user from group chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists. - * 2. If the organization exists - * 3. If the user is the admin of the organization. - * 4. If the user to be removed is a member of the organization. - * @returns Updated group chat. - */ -export const removeUserFromGroupChat: MutationResolvers["removeUserFromGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache[0] == null) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id == context.userId is an admin of organzation. - await adminCheck(context.userId, organization); - - const userIsMemberOfGroupChat = groupChat.users.some((user) => - user.equals(args.userId), - ); - - // Checks if user with _id === args.userId is not a member of groupChat. - if (userIsMemberOfGroupChat === false) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Removes args.userId from users list of groupChat and returns the updated groupChat. - return (await GroupChat.findOneAndUpdate( - { - _id: args.chatId, - }, - { - $set: { - users: groupChat.users.filter( - (user) => user.toString() !== args.userId.toString(), - ), - }, - }, - { - new: true, - }, - ).lean()) as InterfaceGroupChat; - }; diff --git a/src/resolvers/Mutation/sendMessageToChat.ts b/src/resolvers/Mutation/sendMessageToChat.ts new file mode 100644 index 0000000000..a5c7e83558 --- /dev/null +++ b/src/resolvers/Mutation/sendMessageToChat.ts @@ -0,0 +1,73 @@ +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { errors, requestContext } from "../../libraries"; +import { Chat, User, ChatMessage } from "../../models"; +import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR } from "../../constants"; +/** + * This function enables to send message to chat. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the direct chat exists. + * 2. If the user exists + * @returns Chat message. + */ +export const sendMessageToChat: MutationResolvers["sendMessageToChat"] = async ( + _parent, + args, + context, +) => { + const chat = await Chat.findOne({ + _id: args.chatId, + }).lean(); + + if (!chat) { + throw new errors.NotFoundError( + requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + + const currentUserExists = !!(await User.exists({ + _id: context.userId, + })); + + if (currentUserExists === false) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + const now = new Date(); + + const createdChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: chat._id, + sender: context.userId, + messageContent: args.messageContent, + replyTo: args.replyTo, + createdAt: now, + updatedAt: now, + }); + + // add createdDirectChatMessage to directChat + await Chat.updateOne( + { + _id: chat._id, + }, + { + $push: { + messages: createdChatMessage._id, + }, + }, + ); + + // calls subscription + context.pubsub.publish("MESSAGE_SENT_TO_CHAT", { + messageSentToChat: createdChatMessage.toObject(), + }); + + return createdChatMessage.toObject(); +}; diff --git a/src/resolvers/Mutation/sendMessageToDirectChat.ts b/src/resolvers/Mutation/sendMessageToDirectChat.ts deleted file mode 100644 index 65cbf15f2b..0000000000 --- a/src/resolvers/Mutation/sendMessageToDirectChat.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { DirectChat, DirectChatMessage, User } from "../../models"; -import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR } from "../../constants"; -/** - * This function enables to send message to direct chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the direct chat exists. - * 2. If the user exists - * @returns Direct chat message. - */ -export const sendMessageToDirectChat: MutationResolvers["sendMessageToDirectChat"] = - async (_parent, args, context) => { - const directChat = await DirectChat.findOne({ - _id: args.chatId, - }).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - // directChat.users can only have 2 users. So, the following method works. - const receiverIndex = directChat.users.findIndex( - (user) => user.toString() !== context.userId.toString(), - ); - - const createdDirectChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: directChat._id, - sender: context.userId, - receiver: directChat.users[receiverIndex], - messageContent: args.messageContent, - }); - - // add createdDirectChatMessage to directChat - await DirectChat.updateOne( - { - _id: directChat._id, - }, - { - $push: { - messages: createdDirectChatMessage._id, - }, - }, - ); - - // calls subscription - context.pubsub.publish("MESSAGE_SENT_TO_DIRECT_CHAT", { - messageSentToDirectChat: createdDirectChatMessage.toObject(), - }); - - return createdDirectChatMessage.toObject(); - }; diff --git a/src/resolvers/Mutation/sendMessageToGroupChat.ts b/src/resolvers/Mutation/sendMessageToGroupChat.ts deleted file mode 100644 index 93d9f7d5dd..0000000000 --- a/src/resolvers/Mutation/sendMessageToGroupChat.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, GroupChatMessage, User } from "../../models"; -import { - USER_NOT_AUTHORIZED_ERROR, - CHAT_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -/** - * This function enables to send message to group chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists. - * 2. If the user exists - * 3. If the group chat contains the user. - * @returns Group chat message. - */ -export const sendMessageToGroupChat: MutationResolvers["sendMessageToGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserIsAMemberOfGroupChat = groupChat.users.some((user) => - user.equals(context.userId), - ); - - /* - checks if users list of groupChat with _id === args.chatId contains - current user with _id === context.userId - */ - if (currentUserIsAMemberOfGroupChat === false) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - const createdGroupChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: groupChat._id, - sender: context.userId, - createdAt: new Date(), - messageContent: args.messageContent, - }); - - // add createdGroupChatMessage to groupChat - await GroupChat.updateOne( - { - _id: args.chatId, - }, - { - $push: { - messages: createdGroupChatMessage._id, - }, - }, - ); - - // calls subscription - context.pubsub.publish("MESSAGE_SENT_TO_GROUP_CHAT", { - messageSentToGroupChat: createdGroupChatMessage.toObject(), - }); - - return createdGroupChatMessage.toObject(); - }; diff --git a/src/resolvers/Query/chatById.ts b/src/resolvers/Query/chatById.ts new file mode 100644 index 0000000000..81fe769977 --- /dev/null +++ b/src/resolvers/Query/chatById.ts @@ -0,0 +1,26 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { errors } from "../../libraries"; +import { Chat } from "../../models"; +import { CHAT_NOT_FOUND_ERROR } from "../../constants"; +/** + * This query will fetch Chats by a specified id from the database. + * @param _parent- + * @param args - An object that contains `id` of the user. + * @returns An object `Chat`. + * If the `Chat` object is null then it throws `NotFoundError` error. + * @remarks You can learn about GraphQL `Resolvers` + * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. + */ +export const chatById: QueryResolvers["chatById"] = async (_parent, args) => { + const chat = await Chat.findById(args.id).lean(); + + if (!chat) { + throw new errors.NotFoundError( + CHAT_NOT_FOUND_ERROR.DESC, + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + + return chat; +}; diff --git a/src/resolvers/Query/chatsByUserId.ts b/src/resolvers/Query/chatsByUserId.ts new file mode 100644 index 0000000000..57945ad2f6 --- /dev/null +++ b/src/resolvers/Query/chatsByUserId.ts @@ -0,0 +1,23 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; +/** + * This query will fetch all the Chats for the current user from the database. + * @param _parent- + * @param args - An object that contains `id` of the user. + * @returns An object `directChats` that contains all direct chats of the current user. + * If the `directChats` object is null then it throws `NotFoundError` error. + * @remarks You can learn about GraphQL `Resolvers` + * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. + */ +export const chatsByUserId: QueryResolvers["chatsByUserId"] = async ( + _parent, + args, +) => { + const chats = await Chat.find({ + users: args.id, + }).lean(); + + console.log(chats); + + return chats; +}; diff --git a/src/resolvers/Query/directChatById.ts b/src/resolvers/Query/directChatById.ts deleted file mode 100644 index 00a4b9f852..0000000000 --- a/src/resolvers/Query/directChatById.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const directChatById: QueryResolvers["directChatById"] = async ( - _parent, - args, -) => { - const directChat = await DirectChat.findById(args.id).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChat; -}; diff --git a/src/resolvers/Query/directChatsByUserID.ts b/src/resolvers/Query/directChatsByUserID.ts deleted file mode 100644 index efb34e93dd..0000000000 --- a/src/resolvers/Query/directChatsByUserID.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChat } from "../../models"; -/** - * This query will fetch all the Direct chats for the current user from the database. - * @param _parent- - * @param args - An object that contains `id` of the user. - * @returns An object `directChats` that contains all direct chats of the current user. - * If the `directChats` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ -export const directChatsByUserID: QueryResolvers["directChatsByUserID"] = - async (_parent, args) => { - const directChats = await DirectChat.find({ - users: args.id, - }).lean(); - - if (directChats.length === 0) { - throw new errors.NotFoundError( - "DirectChats not found", - "directChats.notFound", - "directChats", - ); - } - - return directChats; - }; diff --git a/src/resolvers/Query/directChatsMessagesByChatID.ts b/src/resolvers/Query/directChatsMessagesByChatID.ts deleted file mode 100644 index 173eada6e5..0000000000 --- a/src/resolvers/Query/directChatsMessagesByChatID.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChatMessage } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const directChatsMessagesByChatID: QueryResolvers["directChatsMessagesByChatID"] = - async (_parent, args) => { - const directChatsMessages = await DirectChatMessage.find({ - directChatMessageBelongsTo: args.id, - }).lean(); - - if (directChatsMessages.length === 0) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChatsMessages; - }; diff --git a/src/resolvers/Query/groupChatById.ts b/src/resolvers/Query/groupChatById.ts deleted file mode 100644 index 43a00ce65d..0000000000 --- a/src/resolvers/Query/groupChatById.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { GroupChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const groupChatById: QueryResolvers["groupChatById"] = async ( - _parent, - args, -) => { - const directChat = await GroupChat.findById(args.id).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChat; -}; diff --git a/src/resolvers/Query/groupChatsByUserId.ts b/src/resolvers/Query/groupChatsByUserId.ts deleted file mode 100644 index a3b3310d3e..0000000000 --- a/src/resolvers/Query/groupChatsByUserId.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { GroupChat } from "../../models"; -/** - * This query will fetch all the Direct chats for the current user from the database. - * @param _parent- - * @param args - An object that contains `id` of the user. - * @returns An object `GroupChat` that contains all direct chats of the current user. - * If the `directChats` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ -export const groupChatsByUserId: QueryResolvers["groupChatsByUserId"] = async ( - _parent, - args, -) => { - const groupChats = await GroupChat.find({ - users: args.id, - }).lean(); - - if (groupChats.length === 0) { - throw new errors.NotFoundError( - "Group Chats not found", - "groupChats.notFound", - "groupChats", - ); - } - - return groupChats; -}; diff --git a/src/resolvers/Query/index.ts b/src/resolvers/Query/index.ts index fc878303d8..e6ca8a74ed 100644 --- a/src/resolvers/Query/index.ts +++ b/src/resolvers/Query/index.ts @@ -13,11 +13,8 @@ import { getAgendaSection } from "./getAgendaSection"; import { checkAuth } from "./checkAuth"; import { customDataByOrganization } from "./customDataByOrganization"; import { customFieldsByOrganization } from "./customFieldsByOrganization"; -import { directChatsByUserID } from "./directChatsByUserID"; -import { directChatsMessagesByChatID } from "./directChatsMessagesByChatID"; -import { directChatById } from "./directChatById"; -import { groupChatById } from "./groupChatById"; -import { groupChatsByUserId } from "./groupChatsByUserId"; +import { chatById } from "./chatById"; +import { chatsByUserId } from "./chatsByUserId"; import { event } from "./event"; import { eventsByOrganization } from "./eventsByOrganization"; import { eventsByOrganizationConnection } from "./eventsByOrganizationConnection"; @@ -68,11 +65,8 @@ export const Query: QueryResolvers = { getCommunityData, customFieldsByOrganization, customDataByOrganization, - directChatsByUserID, - directChatsMessagesByChatID, - directChatById, - groupChatById, - groupChatsByUserId, + chatById, + chatsByUserId, event, eventsByOrganization, eventsByOrganizationConnection, diff --git a/src/resolvers/Subscription/directMessageChat.ts b/src/resolvers/Subscription/directMessageChat.ts deleted file mode 100644 index 38af5cbd3a..0000000000 --- a/src/resolvers/Subscription/directMessageChat.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; - -const CHAT_CHANNEL = "CHAT_CHANNEL"; -/** - * This property contained a `subscribe` field, which is used to subscribe - * the user to get updates for the `CHAT_CHANNEL` event. - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const directMessageChat: SubscriptionResolvers["directMessageChat"] = { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => context.pubsub.asyncIterator(CHAT_CHANNEL), - - (payload) => payload?.directMessageChat, - ), -}; diff --git a/src/resolvers/Subscription/index.ts b/src/resolvers/Subscription/index.ts index c981720fcb..f2f19e4836 100644 --- a/src/resolvers/Subscription/index.ts +++ b/src/resolvers/Subscription/index.ts @@ -1,11 +1,7 @@ import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; -import { directMessageChat } from "./directMessageChat"; -import { messageSentToDirectChat } from "./messageSentToDirectChat"; -import { messageSentToGroupChat } from "./messageSentToGroupChat"; +import { messageSentToChat } from "./messageSentToChat"; import { onPluginUpdate } from "./onPluginUpdate"; export const Subscription: SubscriptionResolvers = { - directMessageChat, - messageSentToDirectChat, - messageSentToGroupChat, + messageSentToChat, onPluginUpdate, }; diff --git a/src/resolvers/Subscription/messageSentToChat.ts b/src/resolvers/Subscription/messageSentToChat.ts new file mode 100644 index 0000000000..936fd104de --- /dev/null +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -0,0 +1,43 @@ +import { withFilter } from "graphql-subscriptions"; +import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; + +const MESSAGE_SENT_TO_CHAT = "MESSAGE_SENT_TO_CHAT"; + +export const filterFunction = async function ( + payload: { messageSentToChat: { chatMessageBelongsTo: string } }, + variables: { userId: string }, +): Promise { + const currentUserId = variables.userId.toString(); + const chatId = payload.messageSentToChat.chatMessageBelongsTo; + + const chat = await Chat.findOne({ + _id: chatId, + }).lean(); + + if (chat) { + const currentUserIsChatMember = chat.users.some((user) => + user.equals(currentUserId), + ); + return currentUserIsChatMember; + } else { + return false; + } +}; +/** + * This property included a `subscribe` method, which is used to + * subscribe the `receiver` and `sender` to receive Chat updates. + * + * @remarks To control updates on a per-client basis, the function uses the `withFilter` + * method imported from `apollo-server-express` module. + * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. + */ +export const messageSentToChat: SubscriptionResolvers["messageSentToChat"] = { + // @ts-expect-error-ts-ignore + subscribe: withFilter( + (_parent, _args, context) => + context.pubsub.asyncIterator([MESSAGE_SENT_TO_CHAT]), + + (payload, variables) => filterFunction(payload, variables), + ), +}; diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts deleted file mode 100644 index 55ce56e603..0000000000 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; - -const MESSAGE_SENT_TO_DIRECT_CHAT = "MESSAGE_SENT_TO_DIRECT_CHAT"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const filterFunction = function (payload: any, variables: any): boolean { - const currentUserId = variables.userId.toString(); - console.log( - currentUserId, - payload.messageSentToDirectChat.receiver.toString(), - payload.messageSentToDirectChat.sender.toString(), - ); - return ( - currentUserId === payload.messageSentToDirectChat.receiver.toString() || - currentUserId === payload.messageSentToDirectChat.sender.toString() - ); -}; -/** - * This property included a `subscribe` method, which is used to - * subscribe the `receiver` and `sender` to receive Direct Chat updates. - * - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const messageSentToDirectChat: SubscriptionResolvers["messageSentToDirectChat"] = - { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => - context.pubsub.asyncIterator([MESSAGE_SENT_TO_DIRECT_CHAT]), - - (payload, variables) => filterFunction(payload, variables), - ), - }; diff --git a/src/resolvers/Subscription/messageSentToGroupChat.ts b/src/resolvers/Subscription/messageSentToGroupChat.ts deleted file mode 100644 index ec45eb30c2..0000000000 --- a/src/resolvers/Subscription/messageSentToGroupChat.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChat } from "../../models"; - -const MESSAGE_SENT_TO_GROUP_CHAT = "MESSAGE_SENT_TO_GROUP_CHAT"; - -/** - * This function is used to filter the subscription payload based on the current user's membership in the group chat. - * - * @param payload - The payload of the subscription message. - * @param context - The context object containing the current user's ID. - * @returns A promise that resolves to a boolean value indicating whether the current user is a member of the group chat. - */ -export const filterFunction = async function ( - payload: any, - variables: any, -): Promise { - const currentUserId = variables.userId; - const groupChatId = payload.messageSentToGroupChat.groupChatMessageBelongsTo; - - const groupChat = await GroupChat.findOne({ - _id: groupChatId, - }).lean(); - - if (groupChat) { - const currentUserIsGroupChatMember = groupChat.users.some((user) => - user.equals(currentUserId), - ); - return currentUserIsGroupChatMember; - } else { - return false; - } -}; -/** - * This property included a `subscribe` method, which is used to - * subscribe the `current_user` to get updates for Group chats. - * - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const messageSentToGroupChat: SubscriptionResolvers["messageSentToGroupChat"] = - { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => - context.pubsub.asyncIterator([MESSAGE_SENT_TO_GROUP_CHAT]), - - (payload, variables) => filterFunction(payload, variables), - ), - }; diff --git a/src/resolvers/index.ts b/src/resolvers/index.ts index 38873057ba..d3dd903ae6 100644 --- a/src/resolvers/index.ts +++ b/src/resolvers/index.ts @@ -18,14 +18,12 @@ import { AgendaSection } from "./AgendaSection"; import { AgendaCategory } from "./AgendaCategory"; import { CheckIn } from "./CheckIn"; import { Comment } from "./Comment"; -import { DirectChat } from "./DirectChat"; -import { DirectChatMessage } from "./DirectChatMessage"; +import { Chat } from "./Chat"; +import { ChatMessage } from "./ChatMessage"; import { Event } from "./Event"; import { EventVolunteer } from "./EventVolunteer"; import { Feedback } from "./Feedback"; import { Fund } from "./Fund"; -import { GroupChat } from "./GroupChat"; -import { GroupChatMessage } from "./GroupChatMessage"; import { MembershipRequest } from "./MembershipRequest"; import { Mutation } from "./Mutation"; import { Organization } from "./Organization"; @@ -50,15 +48,13 @@ const resolvers: Resolvers = { Advertisement, CheckIn, Comment, - DirectChat, - DirectChatMessage, + Chat, + ChatMessage, Event, EventVolunteer, Feedback, Fund, - GroupChat, UserFamily, - GroupChatMessage, MembershipRequest, Mutation, Organization, @@ -89,6 +85,7 @@ const resolversComposition = { "Mutation.addOrganizationImage": [currentUserExists()], "Mutation.blockPluginCreationBySuperadmin": [currentUserExists()], "Mutation.createComment": [currentUserExists()], + "Mutation.createChat": [currentUserExists()], "Mutation.createDirectChat": [currentUserExists()], "Mutation.createGroupChat": [currentUserExists()], "Mutation.createOrganization": [currentUserExists()], diff --git a/src/typeDefs/inputs.ts b/src/typeDefs/inputs.ts index f8d54db61f..1aba325a80 100644 --- a/src/typeDefs/inputs.ts +++ b/src/typeDefs/inputs.ts @@ -16,9 +16,12 @@ export const inputs = gql` userId: ID! } - input createChatInput { - userIds: [ID!]! + input chatInput { + isGroup: Boolean! organizationId: ID + userIds: [ID!]! + name: String + image: String } input createGroupChatInput { diff --git a/src/typeDefs/mutations.ts b/src/typeDefs/mutations.ts index 6bb217447f..5f7d370844 100644 --- a/src/typeDefs/mutations.ts +++ b/src/typeDefs/mutations.ts @@ -33,8 +33,6 @@ export const mutations = gql` addUserImage(file: String!): User! @auth - addUserToGroupChat(userId: ID!, chatId: ID!): GroupChat! @auth - addUserToUserFamily(userId: ID!, familyId: ID!): UserFamily! @auth removeUserFromUserFamily(userId: ID!, familyId: ID!): UserFamily! @auth @@ -43,8 +41,6 @@ export const mutations = gql` createUserFamily(data: createUserFamilyInput!): UserFamily! @auth - adminRemoveGroup(groupId: ID!): GroupChat! @auth - assignUserTag(input: ToggleUserTagAssignInput!): User @auth blockPluginCreationBySuperadmin( @@ -88,7 +84,7 @@ export const mutations = gql` createComment(postId: ID!, data: CommentInput!): Comment @auth - createDirectChat(data: createChatInput!): DirectChat! @auth + createChat(data: chatInput!): Chat createDonation( userId: ID! @@ -110,10 +106,6 @@ export const mutations = gql` data: FundCampaignPledgeInput! ): FundraisingCampaignPledge! @auth - createGroupChat(data: createGroupChatInput!): GroupChat! @auth - - createMessageChat(data: MessageChatInput!): MessageChat! @auth - createOrganization(data: OrganizationInput, file: String): Organization! @auth @role(requires: SUPERADMIN) @@ -198,8 +190,6 @@ export const mutations = gql` removeComment(id: ID!): Comment @auth - removeDirectChat(chatId: ID!, organizationId: ID!): DirectChat! @auth - removeEvent( id: ID! recurringEventDeleteType: RecurringEventMutationType @@ -214,8 +204,6 @@ export const mutations = gql` removeEventVolunteerGroup(id: ID!): EventVolunteerGroup! @auth - removeGroupChat(chatId: ID!): GroupChat! @auth - removeMember(data: UserAndOrganizationInput!): Organization! @auth removeOrganization(id: ID!): UserData! @auth @role(requires: SUPERADMIN) @@ -234,8 +222,6 @@ export const mutations = gql` removeSampleOrganization: Boolean! @auth - removeUserFromGroupChat(userId: ID!, chatId: ID!): GroupChat! @auth - removeUserImage: User! @auth resetCommunity: Boolean! @auth @role(requires: SUPERADMIN) @@ -246,15 +232,11 @@ export const mutations = gql` sendMembershipRequest(organizationId: ID!): MembershipRequest! @auth - sendMessageToDirectChat( - chatId: ID! - messageContent: String! - ): DirectChatMessage! @auth - - sendMessageToGroupChat( + sendMessageToChat( chatId: ID! messageContent: String! - ): GroupChatMessage! @auth + replyTo: ID + ): ChatMessage! @auth signUp(data: UserInput!, file: String): AuthData! diff --git a/src/typeDefs/queries.ts b/src/typeDefs/queries.ts index 4db8616859..b4e40c3e6c 100644 --- a/src/typeDefs/queries.ts +++ b/src/typeDefs/queries.ts @@ -44,15 +44,9 @@ export const queries = gql` customDataByOrganization(organizationId: ID!): [UserCustomData!]! - directChatsByUserID(id: ID!): [DirectChat] + chatById(id: ID!): Chat! - directChatById(id: ID!): DirectChat - - groupChatById(id: ID!): GroupChat - - groupChatsByUserId(id: ID!): [GroupChat] - - directChatsMessagesByChatID(id: ID!): [DirectChatMessage] + chatsByUserId(id: ID!): [Chat] event(id: ID!): Event diff --git a/src/typeDefs/subscriptions.ts b/src/typeDefs/subscriptions.ts index 4c718b9761..f5e3c89c2b 100644 --- a/src/typeDefs/subscriptions.ts +++ b/src/typeDefs/subscriptions.ts @@ -3,9 +3,7 @@ import { gql } from "graphql-tag"; // Place fields alphabetically to ensure easier lookup and navigation. export const subscriptions = gql` type Subscription { - directMessageChat: MessageChat - messageSentToDirectChat(userId: ID!): DirectChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage + messageSentToChat(userId: ID!): ChatMessage onPluginUpdate: Plugin } `; diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index c0be08e183..861423bfc1 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -165,11 +165,6 @@ export const types = gql` userErrors: [CreateCommentError!]! } - type createDirectChatPayload { - directChat: DirectChat - userErrors: [CreateDirectChatError!]! - } - type DeletePayload { success: Boolean! } @@ -178,26 +173,6 @@ export const types = gql` advertisement: Advertisement } - type DirectChat { - _id: ID! - users: [User!]! - messages: [DirectChatMessage] - creator: User - createdAt: DateTime! - updatedAt: DateTime! - organization: Organization - } - - type DirectChatMessage { - _id: ID! - directChatMessageBelongsTo: DirectChat! - sender: User! - receiver: User! - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! - } - type Donation { _id: ID! userId: ID! @@ -373,26 +348,6 @@ export const types = gql` admins: [User!]! } - type GroupChat { - _id: ID! - title: String! - users: [User!]! - messages: [GroupChatMessage] - creator: User - createdAt: DateTime! - updatedAt: DateTime! - organization: Organization! - } - - type GroupChatMessage { - _id: ID! - groupChatMessageBelongsTo: GroupChat! - sender: User! - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! - } - type Language { _id: ID! en: String! @@ -424,16 +379,6 @@ export const types = gql` creator: User } - type MessageChat { - _id: ID! - sender: User! - receiver: User! - message: String! - languageBarrier: Boolean - createdAt: DateTime! - updatedAt: DateTime! - } - type Note { _id: ID! content: String! @@ -772,4 +717,30 @@ export const types = gql` cursor: String! node: User! } + + type Chat { + _id: ID! + isGroup: Boolean! + name: String + createdAt: DateTime! + creator: User + messages: [ChatMessage] + organization: Organization + updatedAt: DateTime! + users: [User!]! + admins: [User] + lastMessageId: String + image: String + } + + type ChatMessage { + _id: ID! + createdAt: DateTime! + chatMessageBelongsTo: Chat! + replyTo: ChatMessage + messageContent: String! + sender: User! + deletedBy: [User] + updatedAt: DateTime! + } `; diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 3ef042af64..e242eadcd8 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -10,8 +10,8 @@ import type { InterfaceCheckIn as InterfaceCheckInModel } from '../models/CheckI import type { InterfaceMessageChat as InterfaceMessageChatModel } from '../models/MessageChat'; import type { InterfaceComment as InterfaceCommentModel } from '../models/Comment'; import type { InterfaceCommunity as InterfaceCommunityModel } from '../models/Community'; -import type { InterfaceDirectChat as InterfaceDirectChatModel } from '../models/DirectChat'; -import type { InterfaceDirectChatMessage as InterfaceDirectChatMessageModel } from '../models/DirectChatMessage'; +import type { InterfaceChat as InterfaceChatModel } from '../models/Chat'; +import type { InterfaceChatMessage as InterfaceChatMessageModel } from '../models/ChatMessage'; import type { InterfaceDonation as InterfaceDonationModel } from '../models/Donation'; import type { InterfaceEvent as InterfaceEventModel } from '../models/Event'; import type { InterfaceEventAttendee as InterfaceEventAttendeeModel } from '../models/EventAttendee'; @@ -23,8 +23,6 @@ import type { InterfaceFund as InterfaceFundModel } from '../models/Fund'; import type { InterfaceFundraisingCampaign as InterfaceFundraisingCampaignModel } from '../models/FundraisingCampaign'; import type { InterfaceFundraisingCampaignPledges as InterfaceFundraisingCampaignPledgesModel } from '../models/FundraisingCampaignPledge'; import type { InterfaceGroup as InterfaceGroupModel } from '../models/Group'; -import type { InterfaceGroupChat as InterfaceGroupChatModel } from '../models/GroupChat'; -import type { InterfaceGroupChatMessage as InterfaceGroupChatMessageModel } from '../models/GroupChatMessage'; import type { InterfaceLanguage as InterfaceLanguageModel } from '../models/Language'; import type { InterfaceMembershipRequest as InterfaceMembershipRequestModel } from '../models/MembershipRequest'; import type { InterfaceMessage as InterfaceMessageModel } from '../models/Message'; @@ -264,6 +262,34 @@ export type CampaignWhereInput = { organizationId?: InputMaybe; }; +export type Chat = { + __typename?: 'Chat'; + _id: Scalars['ID']['output']; + admins?: Maybe>>; + createdAt: Scalars['DateTime']['output']; + creator?: Maybe; + image?: Maybe; + isGroup: Scalars['Boolean']['output']; + lastMessageId?: Maybe; + messages?: Maybe>>; + name?: Maybe; + organization?: Maybe; + updatedAt: Scalars['DateTime']['output']; + users: Array; +}; + +export type ChatMessage = { + __typename?: 'ChatMessage'; + _id: Scalars['ID']['output']; + chatMessageBelongsTo: Chat; + createdAt: Scalars['DateTime']['output']; + deletedBy?: Maybe>>; + messageContent: Scalars['String']['output']; + replyTo?: Maybe; + sender: User; + updatedAt: Scalars['DateTime']['output']; +}; + export type CheckIn = { __typename?: 'CheckIn'; _id: Scalars['ID']['output']; @@ -626,28 +652,6 @@ export type DeletePayload = { success: Scalars['Boolean']['output']; }; -export type DirectChat = { - __typename?: 'DirectChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - creator?: Maybe; - messages?: Maybe>>; - organization?: Maybe; - updatedAt: Scalars['DateTime']['output']; - users: Array; -}; - -export type DirectChatMessage = { - __typename?: 'DirectChatMessage'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - directChatMessageBelongsTo: DirectChat; - messageContent: Scalars['String']['output']; - receiver: User; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type Donation = { __typename?: 'Donation'; _id: Scalars['ID']['output']; @@ -1018,28 +1022,6 @@ export type Group = { updatedAt: Scalars['DateTime']['output']; }; -export type GroupChat = { - __typename?: 'GroupChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - creator?: Maybe; - messages?: Maybe>>; - organization: Organization; - title: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; - users: Array; -}; - -export type GroupChatMessage = { - __typename?: 'GroupChatMessage'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - groupChatMessageBelongsTo: GroupChat; - messageContent: Scalars['String']['output']; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type InvalidCursor = FieldError & { __typename?: 'InvalidCursor'; message: Scalars['String']['output']; @@ -1136,17 +1118,6 @@ export type Message = { videoUrl?: Maybe; }; -export type MessageChat = { - __typename?: 'MessageChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - languageBarrier?: Maybe; - message: Scalars['String']['output']; - receiver: User; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type MessageChatInput = { message: Scalars['String']['input']; receiver: Scalars['ID']['input']; @@ -1176,9 +1147,7 @@ export type Mutation = { addPledgeToFundraisingCampaign: FundraisingCampaignPledge; addUserCustomData: UserCustomData; addUserImage: User; - addUserToGroupChat: GroupChat; addUserToUserFamily: UserFamily; - adminRemoveGroup: GroupChat; assignUserTag?: Maybe; blockPluginCreationBySuperadmin: AppUserProfile; blockUser: User; @@ -1192,8 +1161,8 @@ export type Mutation = { createAgendaCategory: AgendaCategory; createAgendaItem: AgendaItem; createAgendaSection: AgendaSection; + createChat?: Maybe; createComment?: Maybe; - createDirectChat: DirectChat; createDonation: Donation; createEvent: Event; createEventVolunteer: EventVolunteer; @@ -1201,9 +1170,7 @@ export type Mutation = { createFund: Fund; createFundraisingCampaign: FundraisingCampaign; createFundraisingCampaignPledge: FundraisingCampaignPledge; - createGroupChat: GroupChat; createMember: CreateMemberPayload; - createMessageChat: MessageChat; createNote: Note; createOrganization: Organization; createPlugin: Plugin; @@ -1238,13 +1205,11 @@ export type Mutation = { removeAgendaItem: AgendaItem; removeAgendaSection: Scalars['ID']['output']; removeComment?: Maybe; - removeDirectChat: DirectChat; removeEvent: Event; removeEventAttendee: User; removeEventVolunteer: EventVolunteer; removeEventVolunteerGroup: EventVolunteerGroup; removeFundraisingCampaignPledge: FundraisingCampaignPledge; - removeGroupChat: GroupChat; removeMember: Organization; removeOrganization: UserData; removeOrganizationCustomField: OrganizationCustomField; @@ -1253,7 +1218,6 @@ export type Mutation = { removeSampleOrganization: Scalars['Boolean']['output']; removeUserCustomData: UserCustomData; removeUserFamily: UserFamily; - removeUserFromGroupChat: GroupChat; removeUserFromUserFamily: UserFamily; removeUserImage: User; removeUserTag?: Maybe; @@ -1261,8 +1225,7 @@ export type Mutation = { revokeRefreshTokenForUser: Scalars['Boolean']['output']; saveFcmToken: Scalars['Boolean']['output']; sendMembershipRequest: MembershipRequest; - sendMessageToDirectChat: DirectChatMessage; - sendMessageToGroupChat: GroupChatMessage; + sendMessageToChat: ChatMessage; signUp: AuthData; togglePostPin: Post; unassignUserTag?: Maybe; @@ -1347,23 +1310,12 @@ export type MutationAddUserImageArgs = { }; -export type MutationAddUserToGroupChatArgs = { - chatId: Scalars['ID']['input']; - userId: Scalars['ID']['input']; -}; - - export type MutationAddUserToUserFamilyArgs = { familyId: Scalars['ID']['input']; userId: Scalars['ID']['input']; }; -export type MutationAdminRemoveGroupArgs = { - groupId: Scalars['ID']['input']; -}; - - export type MutationAssignUserTagArgs = { input: ToggleUserTagAssignInput; }; @@ -1434,14 +1386,14 @@ export type MutationCreateAgendaSectionArgs = { }; -export type MutationCreateCommentArgs = { - data: CommentInput; - postId: Scalars['ID']['input']; +export type MutationCreateChatArgs = { + data: ChatInput; }; -export type MutationCreateDirectChatArgs = { - data: CreateChatInput; +export type MutationCreateCommentArgs = { + data: CommentInput; + postId: Scalars['ID']['input']; }; @@ -1486,21 +1438,11 @@ export type MutationCreateFundraisingCampaignPledgeArgs = { }; -export type MutationCreateGroupChatArgs = { - data: CreateGroupChatInput; -}; - - export type MutationCreateMemberArgs = { input: UserAndOrganizationInput; }; -export type MutationCreateMessageChatArgs = { - data: MessageChatInput; -}; - - export type MutationCreateNoteArgs = { data: NoteInput; }; @@ -1666,12 +1608,6 @@ export type MutationRemoveCommentArgs = { }; -export type MutationRemoveDirectChatArgs = { - chatId: Scalars['ID']['input']; - organizationId: Scalars['ID']['input']; -}; - - export type MutationRemoveEventArgs = { id: Scalars['ID']['input']; recurringEventDeleteType?: InputMaybe; @@ -1698,11 +1634,6 @@ export type MutationRemoveFundraisingCampaignPledgeArgs = { }; -export type MutationRemoveGroupChatArgs = { - chatId: Scalars['ID']['input']; -}; - - export type MutationRemoveMemberArgs = { data: UserAndOrganizationInput; }; @@ -1739,12 +1670,6 @@ export type MutationRemoveUserFamilyArgs = { }; -export type MutationRemoveUserFromGroupChatArgs = { - chatId: Scalars['ID']['input']; - userId: Scalars['ID']['input']; -}; - - export type MutationRemoveUserFromUserFamilyArgs = { familyId: Scalars['ID']['input']; userId: Scalars['ID']['input']; @@ -1766,15 +1691,10 @@ export type MutationSendMembershipRequestArgs = { }; -export type MutationSendMessageToDirectChatArgs = { - chatId: Scalars['ID']['input']; - messageContent: Scalars['String']['input']; -}; - - -export type MutationSendMessageToGroupChatArgs = { +export type MutationSendMessageToChatArgs = { chatId: Scalars['ID']['input']; messageContent: Scalars['String']['input']; + replyTo?: InputMaybe; }; @@ -2287,12 +2207,11 @@ export type Query = { agendaItemByEvent?: Maybe>>; agendaItemByOrganization?: Maybe>>; agendaItemCategoriesByOrganization?: Maybe>>; + chatById: Chat; + chatsByUserId?: Maybe>>; checkAuth: User; customDataByOrganization: Array; customFieldsByOrganization?: Maybe>>; - directChatById?: Maybe; - directChatsByUserID?: Maybe>>; - directChatsMessagesByChatID?: Maybe>>; event?: Maybe; eventVolunteersByEvent?: Maybe>>; eventsByOrganization?: Maybe>>; @@ -2320,8 +2239,6 @@ export type Query = { getUserTagAncestors?: Maybe>>; getVenueByOrgId?: Maybe>>; getlanguage?: Maybe>>; - groupChatById?: Maybe; - groupChatsByUserId?: Maybe>>; hasSubmittedFeedback?: Maybe; isSampleOrganization: Scalars['Boolean']['output']; joinedOrganizations?: Maybe>>; @@ -2395,27 +2312,22 @@ export type QueryAgendaItemCategoriesByOrganizationArgs = { }; -export type QueryCustomDataByOrganizationArgs = { - organizationId: Scalars['ID']['input']; -}; - - -export type QueryCustomFieldsByOrganizationArgs = { +export type QueryChatByIdArgs = { id: Scalars['ID']['input']; }; -export type QueryDirectChatByIdArgs = { +export type QueryChatsByUserIdArgs = { id: Scalars['ID']['input']; }; -export type QueryDirectChatsByUserIdArgs = { - id: Scalars['ID']['input']; +export type QueryCustomDataByOrganizationArgs = { + organizationId: Scalars['ID']['input']; }; -export type QueryDirectChatsMessagesByChatIdArgs = { +export type QueryCustomFieldsByOrganizationArgs = { id: Scalars['ID']['input']; }; @@ -2560,16 +2472,6 @@ export type QueryGetlanguageArgs = { }; -export type QueryGroupChatByIdArgs = { - id: Scalars['ID']['input']; -}; - - -export type QueryGroupChatsByUserIdArgs = { - id: Scalars['ID']['input']; -}; - - export type QueryHasSubmittedFeedbackArgs = { eventId: Scalars['ID']['input']; userId: Scalars['ID']['input']; @@ -2743,19 +2645,12 @@ export type Status = export type Subscription = { __typename?: 'Subscription'; - directMessageChat?: Maybe; - messageSentToDirectChat?: Maybe; - messageSentToGroupChat?: Maybe; + messageSentToChat?: Maybe; onPluginUpdate?: Maybe; }; -export type SubscriptionMessageSentToDirectChatArgs = { - userId: Scalars['ID']['input']; -}; - - -export type SubscriptionMessageSentToGroupChatArgs = { +export type SubscriptionMessageSentToChatArgs = { userId: Scalars['ID']['input']; }; @@ -3208,17 +3103,14 @@ export type WeekDays = | 'TUESDAY' | 'WEDNESDAY'; -export type CreateChatInput = { +export type ChatInput = { + image?: InputMaybe; + isGroup: Scalars['Boolean']['input']; + name?: InputMaybe; organizationId?: InputMaybe; userIds: Array; }; -export type CreateDirectChatPayload = { - __typename?: 'createDirectChatPayload'; - directChat?: Maybe; - userErrors: Array; -}; - export type CreateGroupChatInput = { organizationId: Scalars['ID']['input']; title: Scalars['String']['input']; @@ -3333,6 +3225,8 @@ export type ResolversTypes = { Boolean: ResolverTypeWrapper; CampaignOrderByInput: CampaignOrderByInput; CampaignWhereInput: CampaignWhereInput; + Chat: ResolverTypeWrapper; + ChatMessage: ResolverTypeWrapper; CheckIn: ResolverTypeWrapper; CheckInCheckOutInput: CheckInCheckOutInput; CheckInStatus: ResolverTypeWrapper & { checkIn?: Maybe, user: ResolversTypes['User'] }>; @@ -3364,8 +3258,6 @@ export type ResolversTypes = { DefaultConnectionPageInfo: ResolverTypeWrapper; DeleteAdvertisementPayload: ResolverTypeWrapper & { advertisement?: Maybe }>; DeletePayload: ResolverTypeWrapper; - DirectChat: ResolverTypeWrapper; - DirectChatMessage: ResolverTypeWrapper; Donation: ResolverTypeWrapper; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3402,8 +3294,6 @@ export type ResolversTypes = { FundraisingCampaignPledge: ResolverTypeWrapper; Gender: Gender; Group: ResolverTypeWrapper; - GroupChat: ResolverTypeWrapper; - GroupChatMessage: ResolverTypeWrapper; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; InvalidCursor: ResolverTypeWrapper; @@ -3422,7 +3312,6 @@ export type ResolversTypes = { MembershipRequest: ResolverTypeWrapper; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: ResolverTypeWrapper; - MessageChat: ResolverTypeWrapper; MessageChatInput: MessageChatInput; MinimumLengthError: ResolverTypeWrapper; MinimumValueError: ResolverTypeWrapper; @@ -3520,8 +3409,7 @@ export type ResolversTypes = { VenueOrderByInput: VenueOrderByInput; VenueWhereInput: VenueWhereInput; WeekDays: WeekDays; - createChatInput: CreateChatInput; - createDirectChatPayload: ResolverTypeWrapper & { directChat?: Maybe, userErrors: Array }>; + chatInput: ChatInput; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3547,6 +3435,8 @@ export type ResolversParentTypes = { AuthData: Omit & { appUserProfile: ResolversParentTypes['AppUserProfile'], user: ResolversParentTypes['User'] }; Boolean: Scalars['Boolean']['output']; CampaignWhereInput: CampaignWhereInput; + Chat: InterfaceChatModel; + ChatMessage: InterfaceChatMessageModel; CheckIn: InterfaceCheckInModel; CheckInCheckOutInput: CheckInCheckOutInput; CheckInStatus: Omit & { checkIn?: Maybe, user: ResolversParentTypes['User'] }; @@ -3577,8 +3467,6 @@ export type ResolversParentTypes = { DefaultConnectionPageInfo: DefaultConnectionPageInfo; DeleteAdvertisementPayload: Omit & { advertisement?: Maybe }; DeletePayload: DeletePayload; - DirectChat: InterfaceDirectChatModel; - DirectChatMessage: InterfaceDirectChatMessageModel; Donation: InterfaceDonationModel; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3608,8 +3496,6 @@ export type ResolversParentTypes = { FundraisingCampaign: InterfaceFundraisingCampaignModel; FundraisingCampaignPledge: InterfaceFundraisingCampaignPledgesModel; Group: InterfaceGroupModel; - GroupChat: InterfaceGroupChatModel; - GroupChatMessage: InterfaceGroupChatMessageModel; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; InvalidCursor: InvalidCursor; @@ -3626,7 +3512,6 @@ export type ResolversParentTypes = { MembershipRequest: InterfaceMembershipRequestModel; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: InterfaceMessageModel; - MessageChat: InterfaceMessageChatModel; MessageChatInput: MessageChatInput; MinimumLengthError: MinimumLengthError; MinimumValueError: MinimumValueError; @@ -3712,8 +3597,7 @@ export type ResolversParentTypes = { Venue: InterfaceVenueModel; VenueInput: VenueInput; VenueWhereInput: VenueWhereInput; - createChatInput: CreateChatInput; - createDirectChatPayload: Omit & { directChat?: Maybe, userErrors: Array }; + chatInput: ChatInput; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3878,6 +3762,34 @@ export type AuthDataResolvers; }; +export type ChatResolvers = { + _id?: Resolver; + admins?: Resolver>>, ParentType, ContextType>; + createdAt?: Resolver; + creator?: Resolver, ParentType, ContextType>; + image?: Resolver, ParentType, ContextType>; + isGroup?: Resolver; + lastMessageId?: Resolver, ParentType, ContextType>; + messages?: Resolver>>, ParentType, ContextType>; + name?: Resolver, ParentType, ContextType>; + organization?: Resolver, ParentType, ContextType>; + updatedAt?: Resolver; + users?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type ChatMessageResolvers = { + _id?: Resolver; + chatMessageBelongsTo?: Resolver; + createdAt?: Resolver; + deletedBy?: Resolver>>, ParentType, ContextType>; + messageContent?: Resolver; + replyTo?: Resolver, ParentType, ContextType>; + sender?: Resolver; + updatedAt?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type CheckInResolvers = { _id?: Resolver; createdAt?: Resolver; @@ -4008,28 +3920,6 @@ export type DeletePayloadResolvers; }; -export type DirectChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - creator?: Resolver, ParentType, ContextType>; - messages?: Resolver>>, ParentType, ContextType>; - organization?: Resolver, ParentType, ContextType>; - updatedAt?: Resolver; - users?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}; - -export type DirectChatMessageResolvers = { - _id?: Resolver; - createdAt?: Resolver; - directChatMessageBelongsTo?: Resolver; - messageContent?: Resolver; - receiver?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type DonationResolvers = { _id?: Resolver; amount?: Resolver; @@ -4201,28 +4091,6 @@ export type GroupResolvers; }; -export type GroupChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - creator?: Resolver, ParentType, ContextType>; - messages?: Resolver>>, ParentType, ContextType>; - organization?: Resolver; - title?: Resolver; - updatedAt?: Resolver; - users?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}; - -export type GroupChatMessageResolvers = { - _id?: Resolver; - createdAt?: Resolver; - groupChatMessageBelongsTo?: Resolver; - messageContent?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type InvalidCursorResolvers = { message?: Resolver; path?: Resolver, ParentType, ContextType>; @@ -4294,17 +4162,6 @@ export type MessageResolvers; }; -export type MessageChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - languageBarrier?: Resolver, ParentType, ContextType>; - message?: Resolver; - receiver?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type MinimumLengthErrorResolvers = { limit?: Resolver; message?: Resolver; @@ -4328,9 +4185,7 @@ export type MutationResolvers>; addUserCustomData?: Resolver>; addUserImage?: Resolver>; - addUserToGroupChat?: Resolver>; addUserToUserFamily?: Resolver>; - adminRemoveGroup?: Resolver>; assignUserTag?: Resolver, ParentType, ContextType, RequireFields>; blockPluginCreationBySuperadmin?: Resolver>; blockUser?: Resolver>; @@ -4344,8 +4199,8 @@ export type MutationResolvers>; createAgendaItem?: Resolver>; createAgendaSection?: Resolver>; + createChat?: Resolver, ParentType, ContextType, RequireFields>; createComment?: Resolver, ParentType, ContextType, RequireFields>; - createDirectChat?: Resolver>; createDonation?: Resolver>; createEvent?: Resolver>; createEventVolunteer?: Resolver>; @@ -4353,9 +4208,7 @@ export type MutationResolvers>; createFundraisingCampaign?: Resolver>; createFundraisingCampaignPledge?: Resolver>; - createGroupChat?: Resolver>; createMember?: Resolver>; - createMessageChat?: Resolver>; createNote?: Resolver>; createOrganization?: Resolver>; createPlugin?: Resolver>; @@ -4390,13 +4243,11 @@ export type MutationResolvers>; removeAgendaSection?: Resolver>; removeComment?: Resolver, ParentType, ContextType, RequireFields>; - removeDirectChat?: Resolver>; removeEvent?: Resolver>; removeEventAttendee?: Resolver>; removeEventVolunteer?: Resolver>; removeEventVolunteerGroup?: Resolver>; removeFundraisingCampaignPledge?: Resolver>; - removeGroupChat?: Resolver>; removeMember?: Resolver>; removeOrganization?: Resolver>; removeOrganizationCustomField?: Resolver>; @@ -4405,7 +4256,6 @@ export type MutationResolvers; removeUserCustomData?: Resolver>; removeUserFamily?: Resolver>; - removeUserFromGroupChat?: Resolver>; removeUserFromUserFamily?: Resolver>; removeUserImage?: Resolver; removeUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4413,8 +4263,7 @@ export type MutationResolvers; saveFcmToken?: Resolver>; sendMembershipRequest?: Resolver>; - sendMessageToDirectChat?: Resolver>; - sendMessageToGroupChat?: Resolver>; + sendMessageToChat?: Resolver>; signUp?: Resolver>; togglePostPin?: Resolver>; unassignUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4602,12 +4451,11 @@ export type QueryResolvers>>, ParentType, ContextType, RequireFields>; agendaItemByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; agendaItemCategoriesByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; + chatById?: Resolver>; + chatsByUserId?: Resolver>>, ParentType, ContextType, RequireFields>; checkAuth?: Resolver; customDataByOrganization?: Resolver, ParentType, ContextType, RequireFields>; customFieldsByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; - directChatById?: Resolver, ParentType, ContextType, RequireFields>; - directChatsByUserID?: Resolver>>, ParentType, ContextType, RequireFields>; - directChatsMessagesByChatID?: Resolver>>, ParentType, ContextType, RequireFields>; event?: Resolver, ParentType, ContextType, RequireFields>; eventVolunteersByEvent?: Resolver>>, ParentType, ContextType, RequireFields>; eventsByOrganization?: Resolver>>, ParentType, ContextType, Partial>; @@ -4635,8 +4483,6 @@ export type QueryResolvers>>, ParentType, ContextType, RequireFields>; getVenueByOrgId?: Resolver>>, ParentType, ContextType, RequireFields>; getlanguage?: Resolver>>, ParentType, ContextType, RequireFields>; - groupChatById?: Resolver, ParentType, ContextType, RequireFields>; - groupChatsByUserId?: Resolver>>, ParentType, ContextType, RequireFields>; hasSubmittedFeedback?: Resolver, ParentType, ContextType, RequireFields>; isSampleOrganization?: Resolver>; joinedOrganizations?: Resolver>>, ParentType, ContextType, Partial>; @@ -4684,9 +4530,7 @@ export type SocialMediaUrlsResolvers = { - directMessageChat?: SubscriptionResolver, "directMessageChat", ParentType, ContextType>; - messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType, RequireFields>; - messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType, RequireFields>; + messageSentToChat?: SubscriptionResolver, "messageSentToChat", ParentType, ContextType, RequireFields>; onPluginUpdate?: SubscriptionResolver, "onPluginUpdate", ParentType, ContextType>; }; @@ -4851,12 +4695,6 @@ export type VenueResolvers; }; -export type CreateDirectChatPayloadResolvers = { - directChat?: Resolver, ParentType, ContextType>; - userErrors?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type Resolvers = { ActionItem?: ActionItemResolvers; ActionItemCategory?: ActionItemCategoryResolvers; @@ -4872,6 +4710,8 @@ export type Resolvers = { Any?: GraphQLScalarType; AppUserProfile?: AppUserProfileResolvers; AuthData?: AuthDataResolvers; + Chat?: ChatResolvers; + ChatMessage?: ChatMessageResolvers; CheckIn?: CheckInResolvers; CheckInStatus?: CheckInStatusResolvers; CheckOut?: CheckOutResolvers; @@ -4893,8 +4733,6 @@ export type Resolvers = { DefaultConnectionPageInfo?: DefaultConnectionPageInfoResolvers; DeleteAdvertisementPayload?: DeleteAdvertisementPayloadResolvers; DeletePayload?: DeletePayloadResolvers; - DirectChat?: DirectChatResolvers; - DirectChatMessage?: DirectChatMessageResolvers; Donation?: DonationResolvers; EmailAddress?: GraphQLScalarType; Error?: ErrorResolvers; @@ -4909,8 +4747,6 @@ export type Resolvers = { FundraisingCampaign?: FundraisingCampaignResolvers; FundraisingCampaignPledge?: FundraisingCampaignPledgeResolvers; Group?: GroupResolvers; - GroupChat?: GroupChatResolvers; - GroupChatMessage?: GroupChatMessageResolvers; InvalidCursor?: InvalidCursorResolvers; JSON?: GraphQLScalarType; Language?: LanguageResolvers; @@ -4922,7 +4758,6 @@ export type Resolvers = { MemberNotFoundError?: MemberNotFoundErrorResolvers; MembershipRequest?: MembershipRequestResolvers; Message?: MessageResolvers; - MessageChat?: MessageChatResolvers; MinimumLengthError?: MinimumLengthErrorResolvers; MinimumValueError?: MinimumValueErrorResolvers; Mutation?: MutationResolvers; @@ -4968,7 +4803,6 @@ export type Resolvers = { UsersConnection?: UsersConnectionResolvers; UsersConnectionEdge?: UsersConnectionEdgeResolvers; Venue?: VenueResolvers; - createDirectChatPayload?: CreateDirectChatPayloadResolvers; }; export type DirectiveResolvers = { diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts new file mode 100644 index 0000000000..b3fa7b468a --- /dev/null +++ b/tests/helpers/chat.ts @@ -0,0 +1,139 @@ +import { nanoid } from "nanoid"; +import type { InterfaceChat, InterfaceChatMessage } from "../../src/models"; +import { Chat, ChatMessage } from "../../src/models"; +import type { TestOrganizationType, TestUserType } from "./userAndOrg"; +import { createTestUserAndOrganization } from "./userAndOrg"; +import type { Document } from "mongoose"; + +export type TestChatType = + | (InterfaceChat & Document) + | null; + +export type TestChatMessageType = + | (InterfaceChatMessage & Document) + | null; + +export const createTestChat = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType] +> => { + const [testUser, testOrganization] = await createTestUserAndOrganization(); + if (testUser && testOrganization) { + const testChat = await Chat.create({ + creatorId: testUser._id, + users: [testUser._id], + organization: testOrganization._id, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), + admins: [testUser._id], + }); + + return [testUser, testOrganization, testChat]; + } else { + return [testUser, testOrganization, null]; + } +}; + +export const createTestChatMessage = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] +> => { + const [testUser, testOrganization, testChat] = await createTestChat(); + + if (testChat?.id) { + const chatMessage = await createChatMessage( + testUser?._id, + testChat?._id.toString(), + ); + + if (testChat && testUser) { + const testChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: testUser._id, + replyTo: chatMessage?._id, + messageContent: `msgContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + return [testUser, testOrganization, testChat, testChatMessage]; + } else { + return [testUser, testOrganization, testChat, null]; + } + } + return [testUser, testOrganization, testChat, null]; +}; + +export const createTestChatMessageWithoutReply = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] +> => { + const [testUser, testOrganization, testChat] = await createTestChat(); + + if (testChat && testUser) { + const testChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: testUser._id, + replyTo: undefined, + messageContent: `msgContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + return [testUser, testOrganization, testChat, testChatMessage]; + } else { + return [testUser, testOrganization, testChat, null]; + } +}; + +export const createTestMessageForMultipleUser = async ( + senderId: string, + organizationId: string, +): Promise => { + const testChat = await Chat.create({ + creatorId: senderId, + users: [senderId], + organization: organizationId, + }); + + await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: senderId, + messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + + return testChat; +}; + +export const createTestChatwithUsers = async ( + creator: string, + organizationId: string, + users: string[], +): Promise => { + const testChat = await Chat.create({ + creatorId: creator, + users: users, + organization: organizationId, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), + }); + return testChat; +}; + +export const createChatMessage = async ( + senderId: string, + chatId: string, +): Promise => { + const chatMessage = await ChatMessage.create({ + chatMessageBelongsTo: chatId, + sender: senderId, + type: "STRING", + messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + }); + + return chatMessage; +}; diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts deleted file mode 100644 index 96d8888e78..0000000000 --- a/tests/helpers/directChat.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { nanoid } from "nanoid"; -import type { - InterfaceDirectChat, - InterfaceDirectChatMessage, -} from "../../src/models"; -import { DirectChat, DirectChatMessage } from "../../src/models"; -import type { TestOrganizationType, TestUserType } from "./userAndOrg"; -import { createTestUserAndOrganization } from "./userAndOrg"; -import type { Document } from "mongoose"; - -export type TestDirectChatType = - | (InterfaceDirectChat & Document) - | null; - -export type TestDirectChatMessageType = - | (InterfaceDirectChatMessage & - Document) - | null; - -export const createTestDirectChat = async (): Promise< - [TestUserType, TestOrganizationType, TestDirectChatType] -> => { - const [testUser, testOrganization] = await createTestUserAndOrganization(); - if (testUser && testOrganization) { - const testDirectChat = await DirectChat.create({ - creatorId: testUser._id, - users: [testUser._id], - organization: testOrganization._id, - }); - - return [testUser, testOrganization, testDirectChat]; - } else { - return [testUser, testOrganization, null]; - } -}; - -export const createTestDirectChatMessage = async (): Promise< - [ - TestUserType, - TestOrganizationType, - TestDirectChatType, - TestDirectChatMessageType, - ] -> => { - const [testUser, testOrganization, testDirectChat] = - await createTestDirectChat(); - - if (testDirectChat && testUser) { - const testDirectChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: testDirectChat._id, - sender: testUser._id, - receiver: testUser._id, - messageContent: `msgContent${nanoid().toLowerCase()}`, - }); - return [testUser, testOrganization, testDirectChat, testDirectChatMessage]; - } else { - return [testUser, testOrganization, testDirectChat, null]; - } -}; - -export const createTestDirectMessageForMultipleUser = async ( - senderId: string, - receiverId: string, - organizationId: string, -): Promise => { - const testDirectChat = await DirectChat.create({ - creatorId: senderId, - users: [senderId], - organization: organizationId, - }); - - await DirectChatMessage.create({ - directChatMessageBelongsTo: testDirectChat._id, - sender: senderId, - receiver: receiverId, - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return testDirectChat; -}; - -export const createTestDirectChatwithUsers = async ( - creator: string, - organizationId: string, - users: string[], -): Promise => { - const testDirectChat = await DirectChat.create({ - creatorId: creator, - users: users, - organization: organizationId, - }); - return testDirectChat; -}; - -export const createDirectChatMessage = async ( - senderId: string, - receiverId: string, - directChatId: string, -): Promise => { - const directChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: directChatId, - sender: senderId, - receiver: receiverId, - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return directChatMessage; -}; diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts deleted file mode 100644 index a7a53b96b9..0000000000 --- a/tests/helpers/groupChat.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { nanoid } from "nanoid"; -import type { - InterfaceGroupChat, - InterfaceGroupChatMessage, -} from "../../src/models"; -import { GroupChat, GroupChatMessage } from "../../src/models"; -import type { TestOrganizationType, TestUserType } from "./userAndOrg"; -import { createTestUserAndOrganization } from "./userAndOrg"; -import type { Document } from "mongoose"; - -export type TestGroupChatType = - | (InterfaceGroupChat & Document) - | null; - -export type TestGroupChatMessageType = - | (InterfaceGroupChatMessage & - Document) - | null; - -export const createTestGroupChat = async (): Promise< - [TestUserType, TestOrganizationType, TestGroupChatType] -> => { - const [testUser, testOrganization] = await createTestUserAndOrganization(); - if (testUser && testOrganization) { - const testGroupChat = await GroupChat.create({ - creatorId: testUser._id, - users: [testUser._id], - organization: testOrganization._id, - title: `title${nanoid().toLowerCase()}`, - }); - - return [testUser, testOrganization, testGroupChat]; - } else { - return [testUser, testOrganization, null]; - } -}; - -export const createTestGroupChatMessage = async (): Promise< - [ - TestUserType, - TestOrganizationType, - TestGroupChatType, - TestGroupChatMessageType, - ] -> => { - const [testUser, testOrganization, testGroupChat] = - await createTestGroupChat(); - - if (testGroupChat && testUser) { - const testGroupChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: testGroupChat._id, - sender: testUser._id, - createdAt: new Date(), - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return [testUser, testOrganization, testGroupChat, testGroupChatMessage]; - } else { - return [testUser, testOrganization, testGroupChat, null]; - } -}; diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts new file mode 100644 index 0000000000..00b752b622 --- /dev/null +++ b/tests/resolvers/Chat/admins.spec.ts @@ -0,0 +1,42 @@ +import "dotenv/config"; +import { admins as adminsResolver } from "../../../src/resolvers/Chat/admins"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { User } from "../../../src/models"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; + +let testChat: TestChatType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [, , testChat] = await createTestChatMessage(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Chat -> admins", () => { + it(`resolves the correct admin users for the given chat`, async () => { + const parent = testChat?.toObject(); + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (!adminsResolver) { + throw new Error("adminsResolver is not defined."); + } + const usersPayload = await adminsResolver(parent, {}, {}); + + const users = await User.find({ + _id: { + $in: testChat?.admins, + }, + }).lean(); + + expect(usersPayload).toEqual(users); + }); +}); diff --git a/tests/resolvers/DirectChat/creator.spec.ts b/tests/resolvers/Chat/creator.spec.ts similarity index 69% rename from tests/resolvers/DirectChat/creator.spec.ts rename to tests/resolvers/Chat/creator.spec.ts index ace3d79c36..52ecda19d7 100644 --- a/tests/resolvers/DirectChat/creator.spec.ts +++ b/tests/resolvers/Chat/creator.spec.ts @@ -1,19 +1,19 @@ import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/DirectChat/creator"; +import { creator as creatorResolver } from "../../../src/resolvers/Chat/creator"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChat } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChat(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChat(); + testChat = userOrgChat[2]; }); afterAll(async () => { @@ -22,7 +22,7 @@ afterAll(async () => { describe("resolvers -> DirectChat -> creator", () => { it(`returns user object for parent.creator`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -30,7 +30,7 @@ describe("resolvers -> DirectChat -> creator", () => { const creatorPayload = await creatorResolver?.(parent, {}, {}); const creator = await User.findOne({ - _id: testDirectChat?.creatorId, + _id: testChat?.creatorId, }).lean(); expect(creatorPayload).toEqual(creator); diff --git a/tests/resolvers/DirectChat/messages.spec.ts b/tests/resolvers/Chat/messages.spec.ts similarity index 57% rename from tests/resolvers/DirectChat/messages.spec.ts rename to tests/resolvers/Chat/messages.spec.ts index fb1632b790..05875ce534 100644 --- a/tests/resolvers/DirectChat/messages.spec.ts +++ b/tests/resolvers/Chat/messages.spec.ts @@ -1,37 +1,37 @@ import "dotenv/config"; -import { messages as messagesResolver } from "../../../src/resolvers/DirectChat/messages"; +import { messages as messagesResolver } from "../../../src/resolvers/Chat/messages"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { DirectChatMessage } from "../../../src/models"; +import { ChatMessage } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChatMessage(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> messages", () => { +describe("resolvers -> Chat -> messages", () => { it(`returns user object for parent.messages`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } const messagesPayload = await messagesResolver?.(parent, {}, {}); - const messages = await DirectChatMessage.find({ + const messages = await ChatMessage.find({ _id: { - $in: testDirectChat?.messages, + $in: testChat?.messages, }, }).lean(); diff --git a/tests/resolvers/DirectChat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts similarity index 61% rename from tests/resolvers/DirectChat/organization.spec.ts rename to tests/resolvers/Chat/organization.spec.ts index 70d8c99476..f8414b6a74 100644 --- a/tests/resolvers/DirectChat/organization.spec.ts +++ b/tests/resolvers/Chat/organization.spec.ts @@ -1,28 +1,28 @@ import "dotenv/config"; +import { organization as organizationResolver } from "../../../src/resolvers/Chat/organization"; +import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { Organization } from "../../../src/models"; -import { organization as organizationResolver } from "../../../src/resolvers/DirectChat/organization"; -import { connect, disconnect } from "../../helpers/db"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChat(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> organization", () => { - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); +describe("resolvers -> Chat -> organization", () => { + it(`resolves the correct organization for the given chat`, async () => { + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -30,22 +30,22 @@ describe("resolvers -> DirectChat -> organization", () => { const organizationPayload = await organizationResolver?.(parent, {}, {}); const organization = await Organization.findOne({ - _id: testDirectChat?.organization, + _id: testChat?.organization, }).lean(); expect(organizationPayload).toEqual(organization); }); - - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); + it("resolves the organization from cache", async () => { + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } + // Simulate the cache resolution logic here (if applicable) const organizationPayload = await organizationResolver?.(parent, {}, {}); const organization = await Organization.findOne({ - _id: testDirectChat?.organization, + _id: testChat?.organization, }).lean(); expect(organizationPayload).toEqual(organization); diff --git a/tests/resolvers/DirectChat/users.spec.ts b/tests/resolvers/Chat/users.spec.ts similarity index 59% rename from tests/resolvers/DirectChat/users.spec.ts rename to tests/resolvers/Chat/users.spec.ts index d30e6fa4cd..541b02b497 100644 --- a/tests/resolvers/DirectChat/users.spec.ts +++ b/tests/resolvers/Chat/users.spec.ts @@ -1,28 +1,28 @@ import "dotenv/config"; -import { users as usersResolver } from "../../../src/resolvers/DirectChat/users"; +import { users as usersResolver } from "../../../src/resolvers/Chat/users"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChatMessage(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> users", () => { +describe("resolvers -> Chat -> users", () => { it(`returns user object for parent.users`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -31,7 +31,7 @@ describe("resolvers -> DirectChat -> users", () => { const users = await User.find({ _id: { - $in: testDirectChat?.users, + $in: testChat?.users, }, }).lean(); diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts new file mode 100644 index 0000000000..b3146fb739 --- /dev/null +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts @@ -0,0 +1,76 @@ +import "dotenv/config"; +import { chatMessageBelongsTo as chatMessageBelongsToResolver } from "../../../src/resolvers/ChatMessage/chatMessageBelongsTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { Chat } from "../../../src/models"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; +import { Types } from "mongoose"; +import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; + +let testChatMessage: TestChatMessageType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const temp = await createTestChatMessage(); + testChatMessage = temp[3]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { + it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { + const parent = testChatMessage?.toObject(); + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof chatMessageBelongsToResolver !== "function") { + throw new Error("chatMessageBelongsToResolver is not a function."); + } + + const chatMessageBelongsToPayload = await chatMessageBelongsToResolver( + parent, + {}, + {}, + ); + + const chatMessageBelongsTo = await Chat.findOne({ + _id: testChatMessage?.chatMessageBelongsTo, + }).lean(); + + expect(chatMessageBelongsToPayload).toEqual(chatMessageBelongsTo); + }); + it(`throws NotFoundError if no directChat exists`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message: string) => message); + + const parent = { + ...testChatMessage?.toObject(), + chatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId + }; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof chatMessageBelongsToResolver !== "function") { + throw new Error("chatMessageBelongsToResolver is not a function."); + } + + try { + // @ts-expect-error - Testing for error + await chatMessageBelongsToResolver(parent, {}, {}); + } catch (error: unknown) { + expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + } + }); +}); diff --git a/tests/resolvers/ChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts new file mode 100644 index 0000000000..162c2d2ba8 --- /dev/null +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -0,0 +1,119 @@ +import "dotenv/config"; +import { replyTo as replyToResolver } from "../../../src/resolvers/ChatMessage/replyTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { ChatMessage } from "../../../src/models"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { + createTestChatMessageWithoutReply, + createTestChatMessage, +} from "../../helpers/chat"; +import { Types } from "mongoose"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../../src/constants"; + +let testChatMessage: TestChatMessageType; +let testChatMessageWithoutReply: TestChatMessageType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + try { + MONGOOSE_INSTANCE = await connect(); + } catch (error) { + console.error("Failed to connect to the database", error); + throw error; + } + + try { + const temp1 = await createTestChatMessage(); + testChatMessage = temp1[3]; + } catch (error) { + console.error("Failed to create test chat message", error); + throw error; + } + + try { + const temp = await createTestChatMessageWithoutReply(); + testChatMessageWithoutReply = temp[3]; + } catch (error) { + console.error("Failed to create test chat message without reply", error); + throw error; + } +}); + +afterAll(async () => { + if (MONGOOSE_INSTANCE) { + await disconnect(MONGOOSE_INSTANCE); + } +}); + +describe("resolvers -> DirectChatMessage -> replyTo", () => { + it(`returns directChat object for parent.replyTo`, async () => { + const parent = testChatMessage ? testChatMessage.toObject() : null; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + try { + const replyToPayload = await replyToResolver(parent, {}, {}); + const replyTo = await ChatMessage.findOne({ + _id: testChatMessage?.replyTo, + }).lean(); + expect(replyToPayload).toEqual(replyTo); + } catch (error) { + console.error("Test failed", error); + throw error; + } + }); + it(`throws NotFoundError if no directChat exists`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message: string) => message); + + const parent = { + ...testChatMessage?.toObject(), + replyTo: new Types.ObjectId(), // Set to a non-existing ObjectId + }; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + try { + // @ts-expect-error - Testing for error + await replyToResolver(parent, {}, {}); + } catch (error: unknown) { + expect(spy).toBeCalledWith(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + } finally { + spy.mockRestore(); // Restore the original function + } + }); + it(`return null if no replyTo`, async () => { + const parent = testChatMessageWithoutReply?.toObject(); + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + const replyToPayload = await replyToResolver(parent, {}, {}); + + const replyTo = null; + + expect(replyToPayload).toEqual(replyTo); + }); +}); diff --git a/tests/resolvers/DirectChatMessage/sender.spec.ts b/tests/resolvers/ChatMessage/sender.spec.ts similarity index 56% rename from tests/resolvers/DirectChatMessage/sender.spec.ts rename to tests/resolvers/ChatMessage/sender.spec.ts index 399de17579..c5bbdd572d 100644 --- a/tests/resolvers/DirectChatMessage/sender.spec.ts +++ b/tests/resolvers/ChatMessage/sender.spec.ts @@ -1,21 +1,21 @@ import "dotenv/config"; -import { sender as senderResolver } from "../../../src/resolvers/DirectChatMessage/sender"; +import { sender as senderResolver } from "../../../src/resolvers/ChatMessage/sender"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; import { Types } from "mongoose"; import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; -let testDirectChatMessage: TestDirectChatMessageType; +let testChatMessage: TestChatMessageType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; + const temp = await createTestChatMessage(); + testChatMessage = temp[3]; }); afterAll(async () => { @@ -24,14 +24,14 @@ afterAll(async () => { describe("resolvers -> DirectChatMessage -> sender", () => { it(`returns user object for parent.sender`, async () => { - const parent = testDirectChatMessage?.toObject(); + const parent = testChatMessage?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } const senderPayload = await senderResolver?.(parent, {}, {}); const sender = await User.findOne({ - _id: testDirectChatMessage?.sender, + _id: testChatMessage?.sender, }).lean(); expect(senderPayload).toEqual(sender); @@ -41,23 +41,25 @@ describe("resolvers -> DirectChatMessage -> sender", () => { const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); - const parent = { - ...testDirectChatMessage?.toObject(), - sender: new Types.ObjectId(), // Set to a non-existing ObjectId - }; + if (testChatMessage?._id) { + const parent = { + ...testChatMessage?.toObject(), + _id: testChatMessage._id, + sender: new Types.ObjectId(), // Set to a non-existing ObjectId + }; - if (!parent) { - throw new Error("Parent object is undefined."); - } + if (!parent) { + throw new Error("Parent object is undefined."); + } - try { - if (senderResolver) { - // @ts-expect-error - Testing for error - await senderResolver(parent, {}, {}); + try { + if (senderResolver) { + await senderResolver(parent, {}, {}); + } + } catch (error: unknown) { + expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } }); }); diff --git a/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts b/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts deleted file mode 100644 index 5ff19d843e..0000000000 --- a/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import "dotenv/config"; -import { directChatMessageBelongsTo as directChatMessageBelongsToResolver } from "../../../src/resolvers/DirectChatMessage/directChatMessageBelongsTo"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { DirectChat } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; -import { Types } from "mongoose"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testDirectChatMessage: TestDirectChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { - it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { - const parent = testDirectChatMessage?.toObject(); - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - if (typeof directChatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); - } - - const directChatMessageBelongsToPayload = - await directChatMessageBelongsToResolver(parent, {}, {}); - - const directChatMessageBelongsTo = await DirectChat.findOne({ - _id: testDirectChatMessage?.directChatMessageBelongsTo, - }).lean(); - - expect(directChatMessageBelongsToPayload).toEqual( - directChatMessageBelongsTo, - ); - }); - it(`throws NotFoundError if no directChat exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testDirectChatMessage?.toObject(), - directChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - if (typeof directChatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); - } - - try { - // @ts-expect-error - Testing for error - await directChatMessageBelongsToResolver(parent, {}, {}); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/DirectChatMessage/receiver.spec.ts b/tests/resolvers/DirectChatMessage/receiver.spec.ts deleted file mode 100644 index 9c39f6b18b..0000000000 --- a/tests/resolvers/DirectChatMessage/receiver.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import { receiver as receiverResolver } from "../../../src/resolvers/DirectChatMessage/receiver"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; -import { Types } from "mongoose"; -import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testDirectChatMessage: TestDirectChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> DirectChatMessage -> receiver", () => { - it(`returns user object for parent.receiver`, async () => { - const parent = testDirectChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const receiverPayload = await receiverResolver?.(parent, {}, {}); - - const receiver = await User.findOne({ - _id: testDirectChatMessage?.receiver, - }).lean(); - - expect(receiverPayload).toEqual(receiver); - }); - it(`throws NotFoundError if no user exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testDirectChatMessage?.toObject(), - receiver: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (receiverResolver) { - // @ts-expect-error - Testing for error - await receiverResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/GroupChat/creator.spec.ts b/tests/resolvers/GroupChat/creator.spec.ts deleted file mode 100644 index 5184e618d4..0000000000 --- a/tests/resolvers/GroupChat/creator.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/GroupChat/creator"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import type { InterfaceGroupChat } from "../../../src/models"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> creator", () => { - it(`returns user object for parent.creator`, async () => { - const parent = testGroupChat?.toObject(); - - const creatorPayload = await creatorResolver?.( - parent ?? ({} as InterfaceGroupChat), - {}, - {}, - ); - - const creator = await User.findOne({ - _id: testGroupChat?.creatorId, - }).lean(); - - expect(creatorPayload).toEqual(creator); - }); -}); diff --git a/tests/resolvers/GroupChat/messages.spec.ts b/tests/resolvers/GroupChat/messages.spec.ts deleted file mode 100644 index 5f69793f0e..0000000000 --- a/tests/resolvers/GroupChat/messages.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import "dotenv/config"; -import { messages as messagesResolver } from "../../../src/resolvers/GroupChat/messages"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { GroupChatMessage } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> messages", () => { - it(`returns user objects for parent.messages`, async () => { - const parent = testGroupChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const messagesPayload = await messagesResolver?.(parent, {}, {}); - - const messages = await GroupChatMessage.find({ - _id: { - $in: testGroupChat?.messages, - }, - }).lean(); - - expect(messagesPayload).toEqual(messages); - }); -}); diff --git a/tests/resolvers/GroupChat/organization.spec.ts b/tests/resolvers/GroupChat/organization.spec.ts deleted file mode 100644 index 2cb0baee86..0000000000 --- a/tests/resolvers/GroupChat/organization.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import "dotenv/config"; -import { organization as organizationResolver } from "../../../src/resolvers/GroupChat/organization"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Organization } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> organization", () => { - it(`returns user objects for parent.organization`, async () => { - const parent = testGroupChat?.toObject(); - if (parent) { - const organizationPayload = await organizationResolver?.(parent, {}, {}); - const organization = await Organization.findOne({ - _id: testGroupChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - } - }); - it(`returns user objects for parent.organization from cache`, async () => { - const parent = testGroupChat?.toObject(); - if (parent) { - const organizationPayload = await organizationResolver?.(parent, {}, {}); - const organization = await Organization.findOne({ - _id: testGroupChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - } - }); -}); diff --git a/tests/resolvers/GroupChat/users.spec.ts b/tests/resolvers/GroupChat/users.spec.ts deleted file mode 100644 index 8616ca5e1a..0000000000 --- a/tests/resolvers/GroupChat/users.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import "dotenv/config"; -import { users as usersResolver } from "../../../src/resolvers/GroupChat/users"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> users", () => { - it(`returns user objects for parent.users`, async () => { - const parent = testGroupChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const usersPayload = await usersResolver?.(parent, {}, {}); - - const users = await User.find({ - _id: { - $in: testGroupChat?.users, - }, - }).lean(); - - expect(usersPayload).toEqual(users); - }); -}); diff --git a/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts b/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts deleted file mode 100644 index 08ade6fde5..0000000000 --- a/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import "dotenv/config"; -import { groupChatMessageBelongsTo as groupChatMessageBelongsToResolver } from "../../../src/resolvers/GroupChatMessage/groupChatMessageBelongsTo"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat } from "../../../src/models"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import type { TestGroupChatMessageType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testGroupChatMessage: TestGroupChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChatMessage(); - testGroupChatMessage = resultArray[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChatMessage -> groupChatMessageBelongsTo", () => { - it(`returns groupChatMessageBelongsTo object for parent.groupChatMessageBelongsTo`, async () => { - const parent = testGroupChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const groupChatMessageBelongsToPayload = - await groupChatMessageBelongsToResolver?.(parent, {}, {}); - - const groupChatMessageBelongsTo = await GroupChat.findOne({ - _id: testGroupChatMessage?.groupChatMessageBelongsTo, - }).lean(); - - expect(groupChatMessageBelongsToPayload).toEqual(groupChatMessageBelongsTo); - }); - it(`throws NotFoundError if no groupChatMessageBelongsTo exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testGroupChatMessage?.toObject(), - groupChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (groupChatMessageBelongsToResolver) { - // @ts-expect-error - Testing for error - await groupChatMessageBelongsToResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/GroupChatMessage/sender.spec.ts b/tests/resolvers/GroupChatMessage/sender.spec.ts deleted file mode 100644 index d9c335d4e2..0000000000 --- a/tests/resolvers/GroupChatMessage/sender.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import { sender as senderResolver } from "../../../src/resolvers/GroupChatMessage/sender"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import type { TestGroupChatMessageType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { Types } from "mongoose"; -import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testGroupChatMessage: TestGroupChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChatMessage(); - testGroupChatMessage = resultArray[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChatMessage -> sender", () => { - it(`returns sender object for parent.sender`, async () => { - const parent = testGroupChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const senderPayload = await senderResolver?.(parent, {}, {}); - - const sender = await User.findOne({ - _id: testGroupChatMessage?.sender, - }).lean(); - - expect(senderPayload).toEqual(sender); - }); - it(`throws NotFoundError if no user exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testGroupChatMessage?.toObject(), - sender: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (senderResolver) { - // @ts-expect-error - Testing for error - await senderResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/Mutation/addUserToGroupChat.spec.ts b/tests/resolvers/Mutation/addUserToGroupChat.spec.ts deleted file mode 100644 index 8f61953651..0000000000 --- a/tests/resolvers/Mutation/addUserToGroupChat.spec.ts +++ /dev/null @@ -1,274 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat, Organization } from "../../../src/models"; -import type { MutationAddUserToGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, -} from "vitest"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_ALREADY_MEMBER_ERROR, - USER_NOT_AUTHORIZED_ADMIN, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testUser = resultArray[0]; - testOrganization = resultArray[1]; - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> addUserToGroupChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationAddUserToGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError if no organization exists with _id === groupChat.organization - for groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is - not an admin of organization with _id === groupChat.organization for groupChat - with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - await Organization.updateOne( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - } - }); - - it(`throws NotFoundError if no user exists with _id === args.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws ConflictError if user with _id === args.userId is already a member - of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_ALREADY_MEMBER_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_ALREADY_MEMBER_ERROR.MESSAGE, - ); - } - }); - - it(`add the groupChat with _id === args.chatId and returns it`, async () => { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - users: [], - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - const addUserToGroupChatPayload = await addUserToGroupChat?.( - {}, - args, - context, - ); - expect(addUserToGroupChatPayload?._id).toEqual(testGroupChat?._id); - expect(addUserToGroupChatPayload?.users).toEqual([testUser?._id]); - }); -}); diff --git a/tests/resolvers/Mutation/adminRemoveGroup.spec.ts b/tests/resolvers/Mutation/adminRemoveGroup.spec.ts deleted file mode 100644 index 584bfd7b49..0000000000 --- a/tests/resolvers/Mutation/adminRemoveGroup.spec.ts +++ /dev/null @@ -1,227 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat, Organization, User } from "../../../src/models"; -import type { MutationAdminRemoveGroupArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { nanoid } from "nanoid"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { adminRemoveGroup as adminRemoveGroupResolver } from "../../../src/resolvers/Mutation/adminRemoveGroup"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultsArray = await createTestGroupChat(); - - testUser = resultsArray[0]; - testOrganization = resultsArray[1]; - testGroupChat = resultsArray[2]; - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementation( - (message) => message, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> adminRemoveGroup", () => { - it("throws an error if the user does not have appUserProfile", async () => { - try { - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - - const context = { - userId: newUser?.id, - }; - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - // console.log(error);? - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - it(`throws NotFoundError if no groupChat exists with _id === args.groupId`, async () => { - try { - const args: MutationAdminRemoveGroupArgs = { - groupId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError if no organization exists with _id === group.organization for - group with _id === args.groupId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if for user with _id === context.userId is not an - admin of orgnanization with _id === args.organizationId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - if (updatedOrganization) cacheOrganizations([updatedOrganization]); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ADMIN.MESSAGE, - ); - } - }); - - it(`deletes the post and returns it`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - if (updatedOrganization) cacheOrganizations([updatedOrganization]); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const adminRemoveGroupPayload = await adminRemoveGroupResolver?.( - {}, - args, - context, - ); - - expect(adminRemoveGroupPayload).toEqual({ - ...testGroupChat?.toObject(), - updatedAt: expect.anything(), - }); - }); -}); diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createChat.spec.ts similarity index 62% rename from tests/resolvers/Mutation/createDirectChat.spec.ts rename to tests/resolvers/Mutation/createChat.spec.ts index 7c46e94092..9013afca46 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createChat.spec.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { MutationCreateDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; +import type { MutationCreateChatArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; import { @@ -29,7 +29,6 @@ let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); const resultsArray = await createTestUserAndOrganization(); - testUser = resultsArray[0]; testOrganization = resultsArray[1]; }); @@ -38,7 +37,7 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> createDirectChat", () => { +describe("resolvers -> Mutation -> createChat", () => { afterEach(() => { vi.doUnmock("../../../src/constants"); vi.resetModules(); @@ -50,20 +49,21 @@ describe("resolvers -> Mutation -> createDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { organizationId: new Types.ObjectId().toString(), userIds: [], + isGroup: true, }, }; const context = { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - await createDirectChatResolver?.({}, args, context); + await createChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( @@ -78,10 +78,11 @@ describe("resolvers -> Mutation -> createDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { - organizationId: testOrganization?.id, + organizationId: testOrganization?._id, userIds: [new Types.ObjectId().toString()], + isGroup: true, }, }; @@ -89,37 +90,60 @@ describe("resolvers -> Mutation -> createDirectChat", () => { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - await createDirectChatResolver?.({}, args, context); + await createChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } }); it(`creates the directChat and returns it`, async () => { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { organizationId: testOrganization?.id, userIds: [testUser?.id], + isGroup: false, }, }; const context = { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - const createDirectChatPayload = await createDirectChatResolver?.( - {}, - args, - context, + const createChatPayload = await createChatResolver?.({}, args, context); + + expect(createChatPayload).toEqual( + expect.objectContaining({ + creatorId: testUser?._id, + users: [testUser?._id], + }), ); + }); + + it(`creates the groupChat and returns it`, async () => { + const args: MutationCreateChatArgs = { + data: { + organizationId: testOrganization?.id, + userIds: [testUser?.id], + isGroup: false, + }, + }; + + const context = { + userId: testUser?.id, + }; + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" + ); + + const createChatPayload = await createChatResolver?.({}, args, context); - expect(createDirectChatPayload).toEqual( + expect(createChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, users: [testUser?._id], diff --git a/tests/resolvers/Mutation/createGroupChat.spec.ts b/tests/resolvers/Mutation/createGroupChat.spec.ts deleted file mode 100644 index 7fc0400b7a..0000000000 --- a/tests/resolvers/Mutation/createGroupChat.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { MutationCreateGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { createGroupChat as createGroupChatResolver } from "../../../src/resolvers/Mutation/createGroupChat"; -import { - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; -let testOrganization: TestOrganizationType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultsArray = await createTestUserAndOrganization(); - - testUser = resultsArray[0]; - testOrganization = resultsArray[1]; - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementation( - (message) => message, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> createGroupChat", () => { - it(`throws NotFoundError if no organization exists with _id === args.data.organizationId`, async () => { - try { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: new Types.ObjectId().toString(), - title: "", - userIds: [], - }, - }; - - const context = { - userId: testUser?.id, - }; - - await createGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws NotFoundError if no user exists for any one of the ids in args.data.userIds`, async () => { - try { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: testOrganization?.id, - title: "", - userIds: [new Types.ObjectId().toString()], - }, - }; - - const context = { - userId: testUser?.id, - }; - - await createGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`creates the groupChat and returns it`, async () => { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: testOrganization?.id, - title: "title", - userIds: [testUser?.id], - }, - }; - - const context = { - userId: testUser?.id, - }; - - const createGroupChatPayload = await createGroupChatResolver?.( - {}, - args, - context, - ); - - expect(createGroupChatPayload).toEqual( - expect.objectContaining({ - title: "title", - creatorId: testUser?._id, - users: [testUser?._id], - organization: testOrganization?._id, - }), - ); - }); -}); diff --git a/tests/resolvers/Mutation/createMessageChat.spec.ts b/tests/resolvers/Mutation/createMessageChat.spec.ts deleted file mode 100644 index d77a2b1d54..0000000000 --- a/tests/resolvers/Mutation/createMessageChat.spec.ts +++ /dev/null @@ -1,239 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { InterfaceMessageChat } from "../../../src/models"; -import { AppUserProfile, User } from "../../../src/models"; -import type { MutationCreateMessageChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { nanoid } from "nanoid"; -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, -} from "vitest"; -import { - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUsers: TestUserType[]; -// let testAppUserProfile: TestAppUserProfileType[]; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - - testUsers = await User.insertMany([ - { - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: "password", - firstName: "firstName", - lastName: "lastName", - }, - { - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: "password", - firstName: "firstName", - lastName: "lastName", - }, - ]); - const appUserProfiles = testUsers.map((user) => ({ - userId: user?._id, - })); - await AppUserProfile.insertMany(appUserProfiles); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> createMessageChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no user exists with _id === args.data.receiver`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: new Types.ObjectId().toString(), - }, - }; - - const context = { - userId: testUsers[0]?.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - it(`throws user not found error if no user exist with id==context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: testUsers[1]?.id, - }, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - // console.log(error); - expect(spy).toHaveBeenCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - it("throws error if receiver user does not have appProfile", async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: newUser.id, - }, - }; - - const context = { - userId: testUsers[0]?.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } - }); - it("throws error if sender user does not have appProfile", async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: testUsers[1]?.id, - }, - }; - - const context = { - userId: newUser.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } - }); - - it(`creates the organization and returns it`, async () => { - const args: MutationCreateMessageChatArgs = { - data: { - message: "message", - receiver: testUsers[1]?.id, - }, - }; - - const pubsub = { - publish: ( - _action: "CHAT_CHANNEL", - _payload: { - directMessageChat: InterfaceMessageChat; - }, - ): { - _action: string; - _payload: { directMessageChat: InterfaceMessageChat }; - } => { - return { _action, _payload }; - }, - }; - - const context = { - userId: testUsers[0]?.id, - pubsub, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - const createMessageChatPayload = await createMessageChatResolver?.( - {}, - args, - context, - ); - - expect(createMessageChatPayload).toEqual( - expect.objectContaining({ - sender: testUsers[0]?._id, - receiver: testUsers[1]?._id, - message: "message", - languageBarrier: false, - }), - ); - }); -}); diff --git a/tests/resolvers/Mutation/removeDirectChat.spec.ts b/tests/resolvers/Mutation/removeDirectChat.spec.ts deleted file mode 100644 index 62bf2af6c8..0000000000 --- a/tests/resolvers/Mutation/removeDirectChat.spec.ts +++ /dev/null @@ -1,228 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { - Organization, - DirectChat, - DirectChatMessage, -} from "../../../src/models"; -import type { MutationRemoveDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - ORGANIZATION_NOT_FOUND_ERROR, - CHAT_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - vi, - afterEach, -} from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testDirectChat: TestDirectChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChat(); - testUser = temp[0]; - testOrganization = temp[1]; - - testDirectChat = await DirectChat.create({ - users: [testUser?._id], - creatorId: testUser?._id, - organization: testOrganization?._id, - }); - - const testDirectChatMessage = temp[2]; - - testDirectChat = await DirectChat.findOneAndUpdate( - { - _id: testDirectChat._id, - }, - { - $push: { - messages: testDirectChatMessage?._id, - }, - }, - { - new: true, - }, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeDirectChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no organization exists with _id === args.organizationId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveDirectChatArgs = { - chatId: "", - organizationId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws NotFoundError if no directChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveDirectChatArgs = { - chatId: new Types.ObjectId().toString(), - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${CHAT_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws UnauthorizedError if user with _id === context.userId is not an admin - of organization with _id === args.organizationId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveDirectChatArgs = { - chatId: testDirectChat?.id, - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - } - }); - - it(`deletes the directChat with _id === args.chatId`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveDirectChatArgs = { - chatId: testDirectChat?.id, - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - const removeDirectChatPayload = await removeDirectChatResolver?.( - {}, - args, - context, - ); - - expect(removeDirectChatPayload).toEqual(testDirectChat?.toObject()); - - const testDeletedDirectChatMessages = await DirectChatMessage.find({ - directChatMessageBelongsTo: testDirectChat?._id, - }).lean(); - - expect(testDeletedDirectChatMessages).toEqual([]); - }); -}); diff --git a/tests/resolvers/Mutation/removeGroupChat.spec.ts b/tests/resolvers/Mutation/removeGroupChat.spec.ts deleted file mode 100644 index eb7bace2c8..0000000000 --- a/tests/resolvers/Mutation/removeGroupChat.spec.ts +++ /dev/null @@ -1,243 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { Organization, GroupChat, GroupChatMessage } from "../../../src/models"; -import type { MutationRemoveGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - afterEach, - vi, -} from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestGroupChatMessage(); - testUser = temp[0]; - testOrganization = temp[1]; - testGroupChat = temp[2]; - const testGroupChatMessage = temp[3]; - testGroupChat = await GroupChat.findOneAndUpdate( - { - _id: testGroupChat?._id, - }, - { - $push: { - messages: testGroupChatMessage?._id, - }, - }, - { - new: true, - }, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeGroupChat", () => { - afterEach(() => { - vi.restoreAllMocks(); - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${CHAT_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws NotFoundError if no organization exists with _id === groupChat.organization - for field organization of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is - not an admin of organization with _id === groupChat.organization for groupChat - with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - } - }); - - it(`deletes the groupChat with _id === args.chatId and all groupChatMessages - associated to it and returns it`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - const removeGroupChatPayload = await removeGroupChatResolver?.( - {}, - args, - context, - ); - - expect(removeGroupChatPayload).toEqual({ - ...testGroupChat?.toObject(), - updatedAt: expect.anything(), - }); - - const testDeletedGroupChatMessages = await GroupChatMessage.find({ - groupChatMessageBelongsTo: testGroupChat?._id, - }).lean(); - - expect(testDeletedGroupChatMessages).toEqual([]); - }); -}); diff --git a/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts b/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts deleted file mode 100644 index 20a18d76d1..0000000000 --- a/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts +++ /dev/null @@ -1,228 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { User, Organization, GroupChat } from "../../../src/models"; -import type { MutationRemoveUserFromGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { removeUserFromGroupChat as removeUserFromGroupChatResolver } from "../../../src/resolvers/Mutation/removeUserFromGroupChat"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { deleteOrganizationFromCache } from "../../../src/services/OrganizationCache/deleteOrganizationFromCache"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestGroupChatMessage(); - testUser = temp[0]; - testOrganization = temp[1]; - testGroupChat = temp[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeUserFromGroupChat", () => { - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - console.log((error as Error).message); - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is not - an admin of the organization of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`throws UnauthorizedError if users field of groupChat with _id === args.chatId - does not contain user with _id === args.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await Organization.updateOne( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - ); - - await User.updateOne( - { - _id: testUser?._id, - }, - { - $push: { - adminFor: testOrganization?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`removes user with _id === args.userId from users list field of groupChat - with _id === args.ChatId and returns the updated groupChat`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => `Translated ${message}`, - ); - - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $push: { - users: testUser?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const removeUserFromGroupChatPayload = - await removeUserFromGroupChatResolver?.({}, args, context); - - const testRemoveUserFromGroupChatPayload = await GroupChat.findOne({ - _id: testGroupChat?._id, - }).lean(); - - expect(removeUserFromGroupChatPayload).toEqual( - testRemoveUserFromGroupChatPayload, - ); - }); - - it(`throws NotFoundError if no organization exists for groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const deletedOrgaization = await Organization.findOneAndDelete({ - _id: testOrganization?._id, - }); - if (deletedOrgaization) - await deleteOrganizationFromCache(deletedOrgaization); - - try { - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); -}); diff --git a/tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts b/tests/resolvers/Mutation/sendMessageToChat.spec.ts similarity index 66% rename from tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts rename to tests/resolvers/Mutation/sendMessageToChat.spec.ts index 3b589b0226..ace1591c82 100644 --- a/tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts +++ b/tests/resolvers/Mutation/sendMessageToChat.spec.ts @@ -2,15 +2,12 @@ import "dotenv/config"; import type { Document } from "mongoose"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { - InterfaceDirectChat, - InterfaceDirectChatMessage, -} from "../../../src/models"; -import { User, Organization, DirectChat } from "../../../src/models"; -import type { MutationSendMessageToDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; +import type { InterfaceChat, InterfaceChatMessage } from "../../../src/models"; +import { User, Organization, Chat } from "../../../src/models"; +import type { MutationSendMessageToChatArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; -import { sendMessageToDirectChat as sendMessageToDirectChatResolver } from "../../../src/resolvers/Mutation/sendMessageToDirectChat"; +import { sendMessageToChat as sendMessageToChatResolver } from "../../../src/resolvers/Mutation/sendMessageToChat"; import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR, @@ -29,8 +26,7 @@ import type { TestUserType } from "../../helpers/userAndOrg"; let MONGOOSE_INSTANCE: typeof mongoose; let testUsers: TestUserType[]; -let testDirectChat: InterfaceDirectChat & - Document; +let testChat: InterfaceChat & Document; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); @@ -61,11 +57,14 @@ beforeAll(async () => { }, ); - testDirectChat = await DirectChat.create({ - title: "title", + testChat = await Chat.create({ + name: "Chat", creatorId: testUsers[0]?._id, organization: testOrganization._id, users: [testUsers[0]?._id, testUsers[1]?._id], + isGroup: false, + createdAt: "23456789", + updatedAt: "23456789", }); }); @@ -85,17 +84,18 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationSendMessageToDirectChatArgs = { + const args: MutationSendMessageToChatArgs = { chatId: new Types.ObjectId().toString(), messageContent: "", }; const context = { userId: testUsers[0]?.id }; - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); - await sendMessageToDirectChatResolver?.({}, args, context); + await sendMessageToChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); @@ -108,8 +108,8 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, + const args: MutationSendMessageToChatArgs = { + chatId: testChat.id, messageContent: "", }; @@ -117,10 +117,11 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { userId: new Types.ObjectId().toString(), }; - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); - await sendMessageToDirectChatResolver?.({}, args, context); + await sendMessageToChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); @@ -128,9 +129,9 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { }); it(`creates the directChatMessage and returns it`, async () => { - await DirectChat.updateOne( + await Chat.updateOne( { - _id: testDirectChat._id, + _id: testChat._id, }, { $push: { @@ -139,20 +140,20 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { }, ); - const args: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, + const args: MutationSendMessageToChatArgs = { + chatId: testChat.id, messageContent: "messageContent", }; const pubsub = { publish: ( - _action: "MESSAGE_SENT_TO_DIRECT_CHAT", + _action: "MESSAGE_SENT_TO_CHAT", _payload: { - messageSentToDirectChat: InterfaceDirectChatMessage; + messageSentToChat: InterfaceChatMessage; }, ): { _action: string; - _payload: { messageSentToDirectChat: InterfaceDirectChatMessage }; + _payload: { messageSentToChat: InterfaceChatMessage }; } => { return { _action, _payload }; }, @@ -163,14 +164,16 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { pubsub, }; - const sendMessageToDirectChatPayload = - await sendMessageToDirectChatResolver?.({}, args, context); + const sendMessageToChatPayload = await sendMessageToChatResolver?.( + {}, + args, + context, + ); - expect(sendMessageToDirectChatPayload).toEqual( + expect(sendMessageToChatPayload).toEqual( expect.objectContaining({ - directChatMessageBelongsTo: testDirectChat._id, + chatMessageBelongsTo: testChat._id, sender: testUsers[0]?._id, - receiver: testUsers[1]?._id, messageContent: "messageContent", }), ); diff --git a/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts b/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts deleted file mode 100644 index b9d0ee8c1a..0000000000 --- a/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts +++ /dev/null @@ -1,170 +0,0 @@ -import "dotenv/config"; -import type { Document } from "mongoose"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { - InterfaceGroupChat, - InterfaceGroupChatMessage, -} from "../../../src/models"; -import { GroupChat } from "../../../src/models"; -import type { MutationSendMessageToGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { sendMessageToGroupChat as sendMessageToGroupChatResolver } from "../../../src/resolvers/Mutation/sendMessageToGroupChat"; -import { - CHAT_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testGroupChat: InterfaceGroupChat & - Document; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestUserAndOrganization(); - testUser = temp[0]; - - const testOrganization = temp[1]; - - testGroupChat = await GroupChat.create({ - title: "title", - creatorId: testUser?._id, - organization: testOrganization?._id, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> sendMessageToGroupChat", () => { - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - messageContent: "", - }; - - const context = { userId: testUser?.id }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError current user with _id === context.userId does not exist`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "", - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if users field of groupChat with _id === args.chatId - does not contain current user with _id === context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`creates the groupChatMessage and returns it`, async () => { - await GroupChat.updateOne( - { - _id: testGroupChat._id, - }, - { - $push: { - users: testUser?._id, - }, - }, - ); - - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "messageContent", - }; - - const pubsub = { - publish: ( - _action: "MESSAGE_SENT_TO_GROUP_CHAT", - _payload: { - messageSentToGroupChat: InterfaceGroupChatMessage; - }, - ): { - _action: string; - _payload: { messageSentToGroupChat: InterfaceGroupChatMessage }; - } => { - return { _action, _payload }; - }, - }; - - const context = { - userId: testUser?.id, - pubsub, - }; - - const sendMessageToGroupChatPayload = - await sendMessageToGroupChatResolver?.({}, args, context); - - expect(sendMessageToGroupChatPayload).toEqual( - expect.objectContaining({ - groupChatMessageBelongsTo: testGroupChat._id, - sender: testUser?._id, - messageContent: "messageContent", - }), - ); - }); -}); diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts new file mode 100644 index 0000000000..9adb1c22ea --- /dev/null +++ b/tests/resolvers/Query/chatById.spec.ts @@ -0,0 +1,37 @@ +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { chatById } from "../../../src/resolvers/Query/chatById"; +import { createTestChat, type TestChatType } from "../../helpers/chat"; +import { connect, disconnect } from "../../helpers/db"; +let MONGOOSE_INSTANCE: typeof mongoose; +let testChat: TestChatType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const temp = await createTestChat(); + testChat = temp[2]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); +describe("resolvers->Query->chatById", () => { + it(`returns the chat with _id === args.id`, async () => { + const args = { + id: testChat?._id?.toString() ?? "", + }; + const chatByIdPayload = await chatById?.({}, args, {}); + expect(chatByIdPayload).toEqual(testChat?.toObject()); + }); + it(`throws chat not found if chat not found for args.id`, async () => { + try { + const args = { + id: new Types.ObjectId().toString(), + }; + await chatById?.({}, args, {}); + } catch (error: unknown) { + expect((error as Error).message).toEqual("Chat not found"); + } + }); +}); diff --git a/tests/resolvers/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts new file mode 100644 index 0000000000..c07ba1dfe2 --- /dev/null +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -0,0 +1,54 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; + +import { chatsByUserId as chatsByUserIdResolver } from "../../../src/resolvers/Query/chatsByUserId"; +import { Chat } from "../../../src/models"; +import type { QueryChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import { createTestChat } from "../../helpers/chat"; +import type { TestUserType } from "../../helpers/userAndOrg"; + +let testUser: TestUserType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const resultArray = await createTestChat(); + testUser = resultArray[0]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> chatsByUserId", () => { + it(`throws NotFoundError if no Chats exists with chats.users + containing user with _id === args.id`, async () => { + try { + const args: QueryChatsByUserIdArgs = { + id: new Types.ObjectId().toString(), + }; + + await chatsByUserIdResolver?.({}, args, {}); + } catch (error: unknown) { + expect((error as Error).message).toEqual("Chats not found"); + } + }); + + it(`returns list of all chats with chat.users containing the user + with _id === args.id`, async () => { + const args: QueryChatsByUserIdArgs = { + id: testUser?._id, + }; + + const chatsByUserIdPayload = await chatsByUserIdResolver?.({}, args, {}); + + const chatsByUserId = await Chat.find({ + users: testUser?._id, + }).lean(); + + expect(chatsByUserIdPayload).toEqual(chatsByUserId); + }); +}); diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts deleted file mode 100644 index 5717c5b56c..0000000000 --- a/tests/resolvers/Query/directChatById.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { directChatById as directChatByIdResolver } from "../../../src/resolvers/Query/directChatById"; -import { DirectChat } from "../../../src/models"; -import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat } from "../../helpers/directChat"; -import type { TestDirectChatType } from "../../helpers/directChat"; - -let testDirectChat: TestDirectChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChat(); - testDirectChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsById", () => { - it(`throws NotFoundError if no directChats exists with directChats._id === args.id`, async () => { - try { - const args: QueryDirectChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatByIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Chat not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryDirectChatsByUserIdArgs = { - id: testDirectChat?._id.toString() ?? "defaultString", - }; - - const directChatsByUserIdPayload = await directChatByIdResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await DirectChat.findById( - testDirectChat?._id, - ).lean(); - console.log(directChatsByUserIdPayload); - console.log(directChatsByUserId); - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/directChatsByUserID.spec.ts b/tests/resolvers/Query/directChatsByUserID.spec.ts deleted file mode 100644 index 780dd529f8..0000000000 --- a/tests/resolvers/Query/directChatsByUserID.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { directChatsByUserID as directChatsByUserIDResolver } from "../../../src/resolvers/Query/directChatsByUserID"; -import { DirectChat } from "../../../src/models"; -import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat } from "../../helpers/directChat"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChat(); - testUser = resultArray[0]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsByUserID", () => { - it(`throws NotFoundError if no directChats exists with directChats.users - containing user with _id === args.id`, async () => { - try { - const args: QueryDirectChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatsByUserIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("DirectChats not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryDirectChatsByUserIdArgs = { - id: testUser?._id, - }; - - const directChatsByUserIdPayload = await directChatsByUserIDResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await DirectChat.find({ - users: testUser?._id, - }).lean(); - - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts b/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts deleted file mode 100644 index 78a22efd44..0000000000 --- a/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import "dotenv/config"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; -import { directChatsMessagesByChatID as directChatsMessagesByChatIDResolver } from "../../../src/resolvers/Query/directChatsMessagesByChatID"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; - -import { DirectChatMessage } from "../../../src/models"; -import type { QueryDirectChatsMessagesByChatIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { - createTestUser, - createTestUserAndOrganization, -} from "../../helpers/userAndOrg"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { - createTestDirectChatwithUsers, - createDirectChatMessage, -} from "../../helpers/directChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testDirectChats: TestDirectChatType[]; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - - const [testUser1, testOrganization] = await createTestUserAndOrganization(); - const testUser2 = await createTestUser(); - - const testDirectChat1 = await createTestDirectChatwithUsers( - testUser1?._id, - testOrganization?._id, - [testUser1?._id, testUser2?._id], - ); - const testDirectChat2 = await createTestDirectChatwithUsers( - testUser2?._id, - testOrganization?._id, - [testUser2?._id], - ); - - testDirectChats = [testDirectChat1, testDirectChat2]; - await createDirectChatMessage( - testUser1?._id, - testUser2?._id, - testDirectChats[0]?._id.toString() || "", - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsMessagesByChatID", () => { - it(`throws NotFoundError if no directChat exists with _id === args.id`, async () => { - try { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatsMessagesByChatIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.DESC); - } - }); - - it(`throws NotFoundError if no directChatMessages exist - for directChat with _id === args.id`, async () => { - try { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: testDirectChats[1]?._id.toString() || "", - }; - - await directChatsMessagesByChatIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.DESC); - } - }); - - it(`returns list of all directChatMessages found - for directChat with _id === args.id`, async () => { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: testDirectChats[0]?._id.toString() || "", - }; - - const directChatsMessagesByChatIdPayload = - await directChatsMessagesByChatIDResolver?.({}, args, {}); - - const directChatMessagesByChatId = await DirectChatMessage.find({ - directChatMessageBelongsTo: testDirectChats[0]?._id, - }).lean(); - - expect(directChatsMessagesByChatIdPayload).toEqual( - directChatMessagesByChatId, - ); - }); -}); diff --git a/tests/resolvers/Query/groupChatById.spec.ts b/tests/resolvers/Query/groupChatById.spec.ts deleted file mode 100644 index 2440387c61..0000000000 --- a/tests/resolvers/Query/groupChatById.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { groupChatById as groupChatByIdResolver } from "../../../src/resolvers/Query/groupChatById"; -import { GroupChat } from "../../../src/models"; -import type { - QueryGroupChatByIdArgs, - QueryGroupChatsByUserIdArgs, -} from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { TestGroupChatType } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsById", () => { - it(`throws NotFoundError if no directChats exists with directChats._id === args.id`, async () => { - try { - const args: QueryGroupChatByIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await groupChatByIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Chat not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryGroupChatsByUserIdArgs = { - id: testGroupChat?._id.toString() ?? "defaultString", - }; - - const directChatsByUserIdPayload = await groupChatByIdResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await GroupChat.findById( - testGroupChat?._id, - ).lean(); - console.log(directChatsByUserIdPayload); - console.log(directChatsByUserId); - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/groupChatsByUserId.spec.ts b/tests/resolvers/Query/groupChatsByUserId.spec.ts deleted file mode 100644 index 7026580b17..0000000000 --- a/tests/resolvers/Query/groupChatsByUserId.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { groupChatsByUserId as groupChatsByUserIdResolver } from "../../../src/resolvers/Query/groupChatsByUserId"; -import { GroupChat } from "../../../src/models"; -import type { QueryGroupChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testUser = resultArray[0]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> groupChatsByUserId", () => { - it(`throws NotFoundError if no groupChats exists with groupChats.users - containing user with _id === args.id`, async () => { - try { - const args: QueryGroupChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await groupChatsByUserIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Group Chats not found"); - } - }); - - it(`returns list of all groupChats with groupChat.users containing the user - with _id === args.id`, async () => { - const args: QueryGroupChatsByUserIdArgs = { - id: testUser?._id, - }; - - const groupChatsByUserIdPayload = await groupChatsByUserIdResolver?.( - {}, - args, - {}, - ); - - const groupChatsByUserId = await GroupChat.find({ - users: testUser?._id, - }).lean(); - - expect(groupChatsByUserIdPayload).toEqual(groupChatsByUserId); - }); -}); diff --git a/tests/resolvers/Subscription/directMessageChat.spec.ts b/tests/resolvers/Subscription/directMessageChat.spec.ts deleted file mode 100644 index 599ad5e937..0000000000 --- a/tests/resolvers/Subscription/directMessageChat.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import "dotenv/config"; -import { describe, it, expect } from "vitest"; - -describe("src -> resolvers -> Subscription -> directMessageChat", () => { - it("should return payload", async () => { - const { directMessageChat: directMessageChatPayload } = await import( - "../../../src/resolvers/Subscription/directMessageChat" - ); - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (chatChannel: string): string => { - return chatChannel; - }, - }, - }; - // @ts-expect-error-ignore - const x = directMessageChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - }); -}); diff --git a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts similarity index 51% rename from tests/resolvers/Subscription/messageSentToDirectChat.spec.ts rename to tests/resolvers/Subscription/messageSentToChat.spec.ts index 8a6fdff245..cf3cc484da 100644 --- a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -2,37 +2,37 @@ import "dotenv/config"; import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; import type { TestUserType } from "../../helpers/userAndOrg"; -import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToDirectChat"; +import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToChat"; +import { Types } from "mongoose"; let MONGOOSE_INSTANCE: typeof mongoose; -let testDirectChatMessage: TestDirectChatMessageType; +let testChatMessage: TestChatMessageType; let testCurrentUser: TestUserType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChatMessage(); + const resultArray = await createTestChatMessage(); testCurrentUser = resultArray[0]; - testDirectChatMessage = resultArray[3]; + testChatMessage = resultArray[3]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { +describe("src -> resolvers -> Subscription -> messageSentToChat", () => { it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { - const { messageSentToDirectChat: messageSentToDirectChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToDirectChat" - ); + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); const _args = {}; const _parent = {}; const context = { pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { return _action; }, }, @@ -42,38 +42,28 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { userId: testCurrentUser?._id, }; const payload = { - messageSentToDirectChat: { - receiver: testDirectChatMessage?.receiver, - sender: testDirectChatMessage?.sender, + messageSentToChat: { + chatMessageBelongsTo: testChatMessage?.chatMessageBelongsTo as string, }, }; // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; + messageSentToChatPayload.payload = payload; // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.subscribe( - _parent, - _args, - context, - ); + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); expect(await filterFunction(payload, variables)).toBe(true); - - // If current User is sender - payload.messageSentToDirectChat.receiver = "receiver"; - expect(await filterFunction(payload, variables)).toBe(true); }); it("user is not notified if it is not a part of DirectChat", async () => { - const { messageSentToDirectChat: messageSentToDirectChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToDirectChat" - ); + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); const _args = {}; const _parent = {}; const context = { pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { return _action; }, }, @@ -84,19 +74,14 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { }; const payload = { - messageSentToDirectChat: { - receiver: "Receiver", - sender: "Sender", + messageSentToChat: { + chatMessageBelongsTo: new Types.ObjectId().toString(), }, }; // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; + messageSentToChatPayload.payload = payload; // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.subscribe( - _parent, - _args, - context, - ); + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); expect(await filterFunction(payload, variables)).toBe(false); }); diff --git a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts deleted file mode 100644 index c1aa13072a..0000000000 --- a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import "dotenv/config"; -import { describe, it, expect, beforeAll, afterAll } from "vitest"; -import { connect, disconnect } from "../../helpers/db"; -import mongoose from "mongoose"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToGroupChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - testGroupChat = (await createTestGroupChatMessage())[2]; -}); -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("src -> resolvers -> Subscription -> messageSentToGroupChat", () => { - it("subscription filter function returns true", async () => { - const { messageSentToGroupChat: messageSentToGroupChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToGroupChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_GROUP_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testGroupChat?.users[0] }, - }; - const variables = { - userId: testGroupChat?.users[0], - }; - const payload = { - messageSentToGroupChat: { - groupChatMessageBelongsTo: testGroupChat?._id, - }, - }; - // @ts-expect-error-ignore - messageSentToGroupChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToGroupChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(true); - }); - it("subscription filter function returns false when group chat not found with the id", async () => { - const { messageSentToGroupChat: messageSentToGroupChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToGroupChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_GROUP_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testGroupChat?.users[0] }, - }; - const payload = { - messageSentToGroupChat: { - groupChatMessageBelongsTo: new mongoose.Types.ObjectId(), - }, - }; - const variables = { - userId: testGroupChat?.users[0], - }; - // @ts-expect-error-ignore - messageSentToGroupChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToGroupChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(false); - }); -});