From a8c02f8b881b225f24131f3377f12b937be86b18 Mon Sep 17 00:00:00 2001 From: Disha Date: Mon, 15 Jul 2024 23:08:11 +0530 Subject: [PATCH 01/50] Updated subscriptions and added mutations for directChat and groupChat --- schema.graphql | 14 +++--- src/index.ts | 2 +- src/models/DirectChat.ts | 5 --- src/resolvers/Mutation/createDirectChat.ts | 25 ----------- src/resolvers/Query/directChatById.ts | 31 +++++++++++++ src/resolvers/Query/groupChatById.ts | 31 +++++++++++++ src/resolvers/Query/groupChatsByUserId.ts | 30 +++++++++++++ src/resolvers/Query/index.ts | 6 +++ .../Subscription/messageSentToDirectChat.ts | 23 +++++++--- .../Subscription/messageSentToGroupChat.ts | 6 +-- src/typeDefs/inputs.ts | 2 +- src/typeDefs/queries.ts | 6 +++ src/typeDefs/subscriptions.ts | 4 +- src/typeDefs/types.ts | 3 +- src/types/generatedGraphQLTypes.ts | 43 ++++++++++++++++--- 15 files changed, 178 insertions(+), 53 deletions(-) create mode 100644 src/resolvers/Query/directChatById.ts create mode 100644 src/resolvers/Query/groupChatById.ts create mode 100644 src/resolvers/Query/groupChatsByUserId.ts diff --git a/schema.graphql b/schema.graphql index 7f03bac2bf..61fe4c97b5 100644 --- a/schema.graphql +++ b/schema.graphql @@ -310,7 +310,7 @@ type CreateCommentPayload { userErrors: [CreateCommentError!]! } -union CreateDirectChatError = OrganizationNotFoundError | UserNotFoundError +union CreateDirectChatError = UserNotFoundError union CreateMemberError = MemberNotFoundError | OrganizationNotFoundError | UserNotAuthorizedAdminError | UserNotAuthorizedError | UserNotFoundError @@ -526,7 +526,7 @@ type DirectChat { createdAt: DateTime! creator: User messages: [DirectChatMessage] - organization: Organization! + organization: Organization updatedAt: DateTime! users: [User!]! } @@ -894,6 +894,7 @@ type Group { type GroupChat { _id: ID! createdAt: DateTime! + title: String! creator: User messages: [GroupChatMessage] organization: Organization! @@ -1439,6 +1440,9 @@ type Query { customFieldsByOrganization(id: ID!): [OrganizationCustomField] directChatsByUserID(id: ID!): [DirectChat] directChatsMessagesByChatID(id: ID!): [DirectChatMessage] + directChatById(id: ID!): DirectChat + groupChatsByUserId(id: ID!): [GroupChat] + groupChatById(id: ID!): GroupChat event(id: ID!): Event eventVolunteersByEvent(id: ID!): [EventVolunteer] eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] @@ -1563,8 +1567,8 @@ enum Status { type Subscription { directMessageChat: MessageChat - messageSentToDirectChat: DirectChatMessage - messageSentToGroupChat: GroupChatMessage + messageSentToDirectChat(userId: ID!): DirectChatMessage + messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } @@ -1976,7 +1980,7 @@ enum WeekDays { } input createChatInput { - organizationId: ID! + organizationId: ID userIds: [ID!]! } diff --git a/src/index.ts b/src/index.ts index 318ea6e19b..74058bf95c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -98,7 +98,7 @@ const wsServer = new WebSocketServer({ // WebSocketServer start listening. const serverCleanup = useServer( // eslint-disable-next-line @typescript-eslint/no-unused-vars - { schema, context: (_ctx, _msg, _args) => ({ pubsub }) }, + { schema, context: (ctx, _msg, args) => ({ pubsub, ctx, args }) }, wsServer, ); diff --git a/src/models/DirectChat.ts b/src/models/DirectChat.ts index 2f08a1e7a9..2223b9c8fc 100644 --- a/src/models/DirectChat.ts +++ b/src/models/DirectChat.ts @@ -47,11 +47,6 @@ const directChatSchema = new Schema( ref: "User", required: true, }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, status: { type: String, required: true, diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts index 6c8675790f..0c7fd0cb10 100644 --- a/src/resolvers/Mutation/createDirectChat.ts +++ b/src/resolvers/Mutation/createDirectChat.ts @@ -22,30 +22,6 @@ export const createDirectChat: MutationResolvers["createDirectChat"] = async ( 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 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 directChat. const usersInDirectChat = []; @@ -71,7 +47,6 @@ export const createDirectChat: MutationResolvers["createDirectChat"] = async ( const createdDirectChat = await DirectChat.create({ creatorId: context.userId, users: usersInDirectChat, - organization: args.data.organizationId, }); // Returns createdDirectChat. diff --git a/src/resolvers/Query/directChatById.ts b/src/resolvers/Query/directChatById.ts new file mode 100644 index 0000000000..00a4b9f852 --- /dev/null +++ b/src/resolvers/Query/directChatById.ts @@ -0,0 +1,31 @@ +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/groupChatById.ts b/src/resolvers/Query/groupChatById.ts new file mode 100644 index 0000000000..43a00ce65d --- /dev/null +++ b/src/resolvers/Query/groupChatById.ts @@ -0,0 +1,31 @@ +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 new file mode 100644 index 0000000000..a3b3310d3e --- /dev/null +++ b/src/resolvers/Query/groupChatsByUserId.ts @@ -0,0 +1,30 @@ +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 f03ee4de14..f20c82b8cf 100644 --- a/src/resolvers/Query/index.ts +++ b/src/resolvers/Query/index.ts @@ -11,6 +11,9 @@ 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 { event } from "./event"; import { eventsByOrganization } from "./eventsByOrganization"; import { eventsByOrganizationConnection } from "./eventsByOrganizationConnection"; @@ -55,6 +58,9 @@ export const Query: QueryResolvers = { customDataByOrganization, directChatsByUserID, directChatsMessagesByChatID, + directChatById, + groupChatById, + groupChatsByUserId, event, eventsByOrganization, eventsByOrganizationConnection, diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index bd937b051f..7d6e7dfef1 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -4,11 +4,23 @@ 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, context: any): boolean { - const { currentUserId } = context.context; +export const filterFunction = function ( + payload: any, + variables: any, + context: any, +): boolean { + console.log(context, "context"); + console.log(context.ctx, "ctx"); + console.log(variables, "var"); + const currentUserId = variables.userId; + console.log( + variables.userId, + payload.messageSentToDirectChat.receiver, + payload.messageSentToDirectChat.sender, + ); return ( - currentUserId === payload.messageSentToDirectChat.receiver || - currentUserId === payload.messageSentToDirectChat.sender + currentUserId === payload.messageSentToDirectChat.receiver.toString() || + currentUserId === payload.messageSentToDirectChat.sender.toString() ); }; /** @@ -26,6 +38,7 @@ export const messageSentToDirectChat: SubscriptionResolvers["messageSentToDirect (_parent, _args, context) => context.pubsub.asyncIterator([MESSAGE_SENT_TO_DIRECT_CHAT]), - (payload, _variables, context) => filterFunction(payload, context), + (payload, variables, context) => + filterFunction(payload, variables, context), ), }; diff --git a/src/resolvers/Subscription/messageSentToGroupChat.ts b/src/resolvers/Subscription/messageSentToGroupChat.ts index 0d4c56fa59..2369b4a5d1 100644 --- a/src/resolvers/Subscription/messageSentToGroupChat.ts +++ b/src/resolvers/Subscription/messageSentToGroupChat.ts @@ -7,9 +7,9 @@ const MESSAGE_SENT_TO_GROUP_CHAT = "MESSAGE_SENT_TO_GROUP_CHAT"; export const filterFunction = async function ( payload: any, - context: any, + variables: any, ): Promise { - const { currentUserId } = context.context; + const currentUserId = variables.userId; const groupChatId = payload.messageSentToGroupChat.groupChatMessageBelongsTo; const groupChat = await GroupChat.findOne({ @@ -40,6 +40,6 @@ export const messageSentToGroupChat: SubscriptionResolvers["messageSentToGroupCh (_parent, _args, context) => context.pubsub.asyncIterator([MESSAGE_SENT_TO_GROUP_CHAT]), - (payload, _variables, context) => filterFunction(payload, context), + (payload, variables) => filterFunction(payload, variables), ), }; diff --git a/src/typeDefs/inputs.ts b/src/typeDefs/inputs.ts index 7d7d365538..220d405ecb 100644 --- a/src/typeDefs/inputs.ts +++ b/src/typeDefs/inputs.ts @@ -18,7 +18,7 @@ export const inputs = gql` input createChatInput { userIds: [ID!]! - organizationId: ID! + organizationId: ID } input createGroupChatInput { diff --git a/src/typeDefs/queries.ts b/src/typeDefs/queries.ts index 3b4154d529..3c38cf753b 100644 --- a/src/typeDefs/queries.ts +++ b/src/typeDefs/queries.ts @@ -36,6 +36,12 @@ export const queries = gql` directChatsByUserID(id: ID!): [DirectChat] + directChatById(id: ID!): DirectChat + + groupChatById(id: ID!): GroupChat + + groupChatsByUserId(id: ID!): [GroupChat] + directChatsMessagesByChatID(id: ID!): [DirectChatMessage] event(id: ID!): Event diff --git a/src/typeDefs/subscriptions.ts b/src/typeDefs/subscriptions.ts index f7c1dff8c1..4c718b9761 100644 --- a/src/typeDefs/subscriptions.ts +++ b/src/typeDefs/subscriptions.ts @@ -4,8 +4,8 @@ import { gql } from "graphql-tag"; export const subscriptions = gql` type Subscription { directMessageChat: MessageChat - messageSentToDirectChat: DirectChatMessage - messageSentToGroupChat: GroupChatMessage + messageSentToDirectChat(userId: ID!): DirectChatMessage + messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } `; diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index 10afcbfccf..c02e81500d 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -183,7 +183,7 @@ export const types = gql` creator: User createdAt: DateTime! updatedAt: DateTime! - organization: Organization! + organization: Organization } type DirectChatMessage { @@ -372,6 +372,7 @@ export const types = gql` type GroupChat { _id: ID! + title: String! users: [User!]! messages: [GroupChatMessage] creator: User diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index da1d6d8d35..8c5eb54a1a 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -604,7 +604,7 @@ export type DirectChat = { createdAt: Scalars['DateTime']['output']; creator?: Maybe; messages?: Maybe>>; - organization: Organization; + organization?: Maybe; updatedAt: Scalars['DateTime']['output']; users: Array; }; @@ -985,6 +985,7 @@ export type GroupChat = { creator?: Maybe; messages?: Maybe>>; organization: Organization; + title: Scalars['String']['output']; updatedAt: Scalars['DateTime']['output']; users: Array; }; @@ -2232,6 +2233,7 @@ export type Query = { checkAuth: User; customDataByOrganization: Array; customFieldsByOrganization?: Maybe>>; + directChatById?: Maybe; directChatsByUserID?: Maybe>>; directChatsMessagesByChatID?: Maybe>>; event?: Maybe; @@ -2257,6 +2259,8 @@ export type Query = { getPlugins?: Maybe>>; getVenueByOrgId?: Maybe>>; getlanguage?: Maybe>>; + groupChatById?: Maybe; + groupChatsByUserId?: Maybe>>; hasSubmittedFeedback?: Maybe; isSampleOrganization: Scalars['Boolean']['output']; joinedOrganizations?: Maybe>>; @@ -2322,6 +2326,11 @@ export type QueryCustomFieldsByOrganizationArgs = { }; +export type QueryDirectChatByIdArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryDirectChatsByUserIdArgs = { id: Scalars['ID']['input']; }; @@ -2445,6 +2454,16 @@ 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']; @@ -2624,6 +2643,16 @@ export type Subscription = { onPluginUpdate?: Maybe; }; + +export type SubscriptionMessageSentToDirectChatArgs = { + userId: Scalars['ID']['input']; +}; + + +export type SubscriptionMessageSentToGroupChatArgs = { + userId: Scalars['ID']['input']; +}; + export type ToggleUserTagAssignInput = { tagId: Scalars['ID']['input']; userId: Scalars['ID']['input']; @@ -3068,7 +3097,7 @@ export type WeekDays = | 'WEDNESDAY'; export type CreateChatInput = { - organizationId: Scalars['ID']['input']; + organizationId?: InputMaybe; userIds: Array; }; @@ -3857,7 +3886,7 @@ export type DirectChatResolvers; creator?: Resolver, ParentType, ContextType>; messages?: Resolver>>, ParentType, ContextType>; - organization?: Resolver; + organization?: Resolver, ParentType, ContextType>; updatedAt?: Resolver; users?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -4050,6 +4079,7 @@ export type GroupChatResolvers, ParentType, ContextType>; messages?: Resolver>>, ParentType, ContextType>; organization?: Resolver; + title?: Resolver; updatedAt?: Resolver; users?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; @@ -4445,6 +4475,7 @@ export type QueryResolvers; 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>; @@ -4470,6 +4501,8 @@ export type QueryResolvers>>, ParentType, ContextType>; 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>; @@ -4518,8 +4551,8 @@ export type SocialMediaUrlsResolvers = { directMessageChat?: SubscriptionResolver, "directMessageChat", ParentType, ContextType>; - messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType>; - messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType>; + messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType, RequireFields>; + messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType, RequireFields>; onPluginUpdate?: SubscriptionResolver, "onPluginUpdate", ParentType, ContextType>; }; From fe6907d7a7836fe6b6dd5bdc45c7487e9108002c Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Tue, 16 Jul 2024 12:19:44 +0530 Subject: [PATCH 02/50] Update index.ts --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 74058bf95c..318ea6e19b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -98,7 +98,7 @@ const wsServer = new WebSocketServer({ // WebSocketServer start listening. const serverCleanup = useServer( // eslint-disable-next-line @typescript-eslint/no-unused-vars - { schema, context: (ctx, _msg, args) => ({ pubsub, ctx, args }) }, + { schema, context: (_ctx, _msg, _args) => ({ pubsub }) }, wsServer, ); From 3a9799dccfc065ec43494e9b087a25ba362c354a Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Tue, 16 Jul 2024 12:20:59 +0530 Subject: [PATCH 03/50] Update messageSentToDirectChat.ts --- src/resolvers/Subscription/messageSentToDirectChat.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 7d6e7dfef1..355f6dd132 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -9,15 +9,8 @@ export const filterFunction = function ( variables: any, context: any, ): boolean { - console.log(context, "context"); - console.log(context.ctx, "ctx"); - console.log(variables, "var"); + const currentUserId = variables.userId; - console.log( - variables.userId, - payload.messageSentToDirectChat.receiver, - payload.messageSentToDirectChat.sender, - ); return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || currentUserId === payload.messageSentToDirectChat.sender.toString() From 2fa65b1895d47adcb82e044efe195b8e58f4afe9 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Tue, 16 Jul 2024 15:24:04 +0530 Subject: [PATCH 04/50] Update createDirectChat.spec.ts --- tests/resolvers/Mutation/createDirectChat.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createDirectChat.spec.ts index ee51c5e9d2..22e1130957 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createDirectChat.spec.ts @@ -122,8 +122,7 @@ describe("resolvers -> Mutation -> createDirectChat", () => { expect(createDirectChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, - users: [testUser?._id], - organization: testOrganization?._id, + users: [testUser?._id] }), ); }); From f68bb010d06bfdfc30c003642bb7a3f498123d0b Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Tue, 16 Jul 2024 15:24:40 +0530 Subject: [PATCH 05/50] Update createDirectChat.spec.ts --- tests/resolvers/Mutation/createDirectChat.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createDirectChat.spec.ts index ee51c5e9d2..22e1130957 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createDirectChat.spec.ts @@ -122,8 +122,7 @@ describe("resolvers -> Mutation -> createDirectChat", () => { expect(createDirectChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, - users: [testUser?._id], - organization: testOrganization?._id, + users: [testUser?._id] }), ); }); From f7089b9f6b0b0ea43ef27dc8a726b5baecac16e6 Mon Sep 17 00:00:00 2001 From: Disha Date: Tue, 16 Jul 2024 22:40:04 +0530 Subject: [PATCH 06/50] fix: linting errors --- src/resolvers/Mutation/createDirectChat.ts | 5 +---- src/resolvers/Subscription/messageSentToDirectChat.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts index 0c7fd0cb10..f8b1601c36 100644 --- a/src/resolvers/Mutation/createDirectChat.ts +++ b/src/resolvers/Mutation/createDirectChat.ts @@ -1,12 +1,9 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { User, Organization, DirectChat } from "../../models"; +import { User, DirectChat } from "../../models"; import { errors, requestContext } from "../../libraries"; import { USER_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 create direct chat. * @param _parent - parent of current request diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 355f6dd132..4dea9102c8 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -7,7 +7,7 @@ const MESSAGE_SENT_TO_DIRECT_CHAT = "MESSAGE_SENT_TO_DIRECT_CHAT"; export const filterFunction = function ( payload: any, variables: any, - context: any, + _context: any, ): boolean { const currentUserId = variables.userId; From 2fe535363c0b4c7a89f5255a9fbe7c183a001cfe Mon Sep 17 00:00:00 2001 From: Disha Date: Tue, 16 Jul 2024 23:04:50 +0530 Subject: [PATCH 07/50] fix: lint errors --- src/resolvers/Subscription/messageSentToDirectChat.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 4dea9102c8..b3d6be2e33 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -7,7 +7,6 @@ const MESSAGE_SENT_TO_DIRECT_CHAT = "MESSAGE_SENT_TO_DIRECT_CHAT"; export const filterFunction = function ( payload: any, variables: any, - _context: any, ): boolean { const currentUserId = variables.userId; @@ -31,7 +30,7 @@ export const messageSentToDirectChat: SubscriptionResolvers["messageSentToDirect (_parent, _args, context) => context.pubsub.asyncIterator([MESSAGE_SENT_TO_DIRECT_CHAT]), - (payload, variables, context) => - filterFunction(payload, variables, context), + (payload, variables) => + filterFunction(payload, variables), ), }; From 7e31c1496898d7bf7af45f12476e4568787374b2 Mon Sep 17 00:00:00 2001 From: Disha Date: Tue, 16 Jul 2024 23:11:33 +0530 Subject: [PATCH 08/50] fix: formatting issues --- src/resolvers/Mutation/createDirectChat.ts | 4 +--- src/resolvers/Subscription/messageSentToDirectChat.ts | 9 ++------- tests/resolvers/Mutation/createDirectChat.spec.ts | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts index f8b1601c36..3d0438564c 100644 --- a/src/resolvers/Mutation/createDirectChat.ts +++ b/src/resolvers/Mutation/createDirectChat.ts @@ -1,9 +1,7 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; import { User, DirectChat } from "../../models"; import { errors, requestContext } from "../../libraries"; -import { - USER_NOT_FOUND_ERROR, -} from "../../constants"; +import { USER_NOT_FOUND_ERROR } from "../../constants"; /** * This function enables to create direct chat. * @param _parent - parent of current request diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index b3d6be2e33..9810befdac 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -4,11 +4,7 @@ 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 { - +export const filterFunction = function (payload: any, variables: any): boolean { const currentUserId = variables.userId; return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || @@ -30,7 +26,6 @@ export const messageSentToDirectChat: SubscriptionResolvers["messageSentToDirect (_parent, _args, context) => context.pubsub.asyncIterator([MESSAGE_SENT_TO_DIRECT_CHAT]), - (payload, variables) => - filterFunction(payload, variables), + (payload, variables) => filterFunction(payload, variables), ), }; diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createDirectChat.spec.ts index 22e1130957..7c46e94092 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createDirectChat.spec.ts @@ -122,7 +122,7 @@ describe("resolvers -> Mutation -> createDirectChat", () => { expect(createDirectChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, - users: [testUser?._id] + users: [testUser?._id], }), ); }); From 9c44ea4c95704666867729062a58b34ede36667f Mon Sep 17 00:00:00 2001 From: Disha Date: Tue, 16 Jul 2024 23:25:19 +0530 Subject: [PATCH 09/50] fix: formatting issues --- tests/resolvers/Mutation/createDirectChat.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createDirectChat.spec.ts index 22e1130957..7c46e94092 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createDirectChat.spec.ts @@ -122,7 +122,7 @@ describe("resolvers -> Mutation -> createDirectChat", () => { expect(createDirectChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, - users: [testUser?._id] + users: [testUser?._id], }), ); }); From fa5f6ecf2185d5e1b24e524b9162ed108484cad7 Mon Sep 17 00:00:00 2001 From: Disha Date: Tue, 16 Jul 2024 23:44:07 +0530 Subject: [PATCH 10/50] fix: test cases --- .../Subscription/messageSentToGroupChat.spec.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts index 5474a0ea8b..74ca3879ea 100644 --- a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts @@ -26,13 +26,8 @@ describe("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: { @@ -44,7 +39,7 @@ describe("src -> resolvers -> Subscription -> messageSentToGroupChat", () => { // @ts-expect-error-ignore const x = messageSentToGroupChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); - expect(await filterFunction(payload, context)).toBe(true); + 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 } = From 3db8381161b627b9b64937b162bfb0499f38a934 Mon Sep 17 00:00:00 2001 From: Disha Date: Wed, 17 Jul 2024 00:01:31 +0530 Subject: [PATCH 11/50] fix test cases --- .../Subscription/messageSentToDirectChat.spec.ts | 12 +++++++++--- .../Subscription/messageSentToGroupChat.spec.ts | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts b/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts index 4eab859433..8a6fdff245 100644 --- a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts @@ -38,6 +38,9 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { }, context: { currentUserId: testCurrentUser?._id }, }; + const variables = { + userId: testCurrentUser?._id, + }; const payload = { messageSentToDirectChat: { receiver: testDirectChatMessage?.receiver, @@ -53,11 +56,11 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { context, ); expect(x).not.toBe(null); - expect(await filterFunction(payload, context)).toBe(true); + expect(await filterFunction(payload, variables)).toBe(true); // If current User is sender payload.messageSentToDirectChat.receiver = "receiver"; - expect(await filterFunction(payload, context)).toBe(true); + expect(await filterFunction(payload, variables)).toBe(true); }); it("user is not notified if it is not a part of DirectChat", async () => { @@ -76,6 +79,9 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { }, context: { currentUserId: testCurrentUser?._id }, }; + const variables = { + userId: testCurrentUser?._id, + }; const payload = { messageSentToDirectChat: { @@ -92,6 +98,6 @@ describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { context, ); expect(x).not.toBe(null); - expect(await filterFunction(payload, context)).toBe(false); + expect(await filterFunction(payload, variables)).toBe(false); }); }); diff --git a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts index 74ca3879ea..c1aa13072a 100644 --- a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts @@ -26,8 +26,16 @@ describe("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] + userId: testGroupChat?.users[0], }; const payload = { messageSentToGroupChat: { @@ -62,11 +70,14 @@ describe("src -> resolvers -> Subscription -> 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, context)).toBe(false); + expect(await filterFunction(payload, variables)).toBe(false); }); }); From a1379bf20f39f4166d11d4de455ccb76f22f283c Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 12:06:50 +0530 Subject: [PATCH 12/50] Update messageSentToDirectChat.ts --- src/resolvers/Subscription/messageSentToDirectChat.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 9810befdac..c1a549126f 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -6,6 +6,7 @@ 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; + console.log(currentUserId, payload.messageSentToDirectChat.receiver.toString(), payload.messageSentToDirectChat.sender.toString()); return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || currentUserId === payload.messageSentToDirectChat.sender.toString() From bd98a6bce2acf38c24166952e9486d54d97b5fd1 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 12:20:33 +0530 Subject: [PATCH 13/50] Update messageSentToDirectChat.ts --- src/resolvers/Subscription/messageSentToDirectChat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index c1a549126f..5dc5355a5e 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -5,7 +5,7 @@ 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; + const currentUserId = variables.userId.toString(); console.log(currentUserId, payload.messageSentToDirectChat.receiver.toString(), payload.messageSentToDirectChat.sender.toString()); return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || From 7ec17731d27357b77de632f9c96daadad9a71c4b Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 13:13:01 +0530 Subject: [PATCH 14/50] added test cases for query directChatById --- tests/resolvers/Query/directChatById.spec.ts | 59 ++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/resolvers/Query/directChatById.spec.ts diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts new file mode 100644 index 0000000000..f485f49deb --- /dev/null +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -0,0 +1,59 @@ +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, TestDirectChatType} from "../../helpers/directChat"; +import type { TestUserType, } from "../../helpers/userAndOrg"; + +let testUser: TestUserType; +let testDirectChat: TestDirectChatType +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const resultArray = await createTestDirectChat(); + testUser = resultArray[0]; + 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("DirectChats 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, + }; + + const directChatsByUserIdPayload = await directChatByIdResolver?.( + {}, + args, + {}, + ); + + const directChatsByUserId = await DirectChat.find({ + users: testDirectChat?._id, + }).lean(); + + expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); + }); +}); From 3781ede9727c2f8596d37e6c9d27d5553d1de2c4 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 13:34:58 +0530 Subject: [PATCH 15/50] Update directChatById.spec.ts --- tests/resolvers/Query/directChatById.spec.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts index f485f49deb..0d35f36934 100644 --- a/tests/resolvers/Query/directChatById.spec.ts +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -7,17 +7,15 @@ import { directChatById as directChatByIdResolver } from "../../../src/resolvers import { DirectChat } from "../../../src/models"; import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat, TestDirectChatType} from "../../helpers/directChat"; -import type { TestUserType, } from "../../helpers/userAndOrg"; +import { createTestDirectChat, } from "../../helpers/directChat"; +import type { TestDirectChatType } from "../../helpers/directChat"; -let testUser: TestUserType; let testDirectChat: TestDirectChatType let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); const resultArray = await createTestDirectChat(); - testUser = resultArray[0]; testDirectChat = resultArray[2]; }); @@ -34,7 +32,7 @@ describe("resolvers -> Query -> directChatsById", () => { await directChatByIdResolver?.({}, args, {}); } catch (error: unknown) { - expect((error as Error).message).toEqual("DirectChats not found"); + expect((error as Error).message).toEqual("Chat not found"); } }); @@ -51,7 +49,7 @@ describe("resolvers -> Query -> directChatsById", () => { ); const directChatsByUserId = await DirectChat.find({ - users: testDirectChat?._id, + _id: testDirectChat?._id, }).lean(); expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); From 8aaf5f3bb8cd88aab8edd3e8f61f92ebf9c3c562 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 14:25:21 +0530 Subject: [PATCH 16/50] Update directChatById.spec.ts --- tests/resolvers/Query/directChatById.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts index 0d35f36934..31447d9af0 100644 --- a/tests/resolvers/Query/directChatById.spec.ts +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -51,7 +51,8 @@ describe("resolvers -> Query -> directChatsById", () => { const directChatsByUserId = await DirectChat.find({ _id: testDirectChat?._id, }).lean(); - + console.log(directChatsByUserIdPayload); + console.log(directChatsByUserId); expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); }); }); From e83657dc159b1fe3b0d43b69090d9f9bb380ff08 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Thu, 18 Jul 2024 16:38:33 +0530 Subject: [PATCH 17/50] Update directChatById.spec.ts --- tests/resolvers/Query/directChatById.spec.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts index 31447d9af0..64ccc29373 100644 --- a/tests/resolvers/Query/directChatById.spec.ts +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -48,9 +48,7 @@ describe("resolvers -> Query -> directChatsById", () => { {}, ); - const directChatsByUserId = await DirectChat.find({ - _id: testDirectChat?._id, - }).lean(); + const directChatsByUserId = await DirectChat.findById(testDirectChat?._id).lean(); console.log(directChatsByUserIdPayload); console.log(directChatsByUserId); expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); From 23a96761dc4deb5e3d68cbd9af9d6977583f0528 Mon Sep 17 00:00:00 2001 From: Disha Date: Thu, 18 Jul 2024 22:39:03 +0530 Subject: [PATCH 18/50] Added test cases --- .../Subscription/messageSentToDirectChat.ts | 6 +- src/types/generatedGraphQLTypes.ts | 4 +- tests/resolvers/Query/directChatById.spec.ts | 8 ++- tests/resolvers/Query/groupChatById.spec.ts | 58 +++++++++++++++++++ .../Query/groupChatsByUserId.spec.ts | 58 +++++++++++++++++++ 5 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 tests/resolvers/Query/groupChatById.spec.ts create mode 100644 tests/resolvers/Query/groupChatsByUserId.spec.ts diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 5dc5355a5e..55ce56e603 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -6,7 +6,11 @@ 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()); + console.log( + currentUserId, + payload.messageSentToDirectChat.receiver.toString(), + payload.messageSentToDirectChat.sender.toString(), + ); return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || currentUserId === payload.messageSentToDirectChat.sender.toString() diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 4c05807c81..70954162f5 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -3231,7 +3231,7 @@ export type DirectiveResolverFn TResult | Promise; /** Mapping of union types */ -export type ResolversUnionTypes<_RefType extends Record> = { +export type ResolversUnionTypes> = { ConnectionError: ( InvalidCursor ) | ( MaximumValueError ); CreateAdminError: ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); CreateCommentError: ( PostNotFoundError ); @@ -3240,7 +3240,7 @@ export type ResolversUnionTypes<_RefType extends Record> = { }; /** Mapping of interface types */ -export type ResolversInterfaceTypes<_RefType extends Record> = { +export type ResolversInterfaceTypes> = { ConnectionPageInfo: ( DefaultConnectionPageInfo ); Error: ( MemberNotFoundError ) | ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( PostNotFoundError ) | ( UnauthenticatedError ) | ( UnauthorizedError ) | ( UserNotAuthorizedAdminError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); FieldError: ( InvalidCursor ) | ( MaximumLengthError ) | ( MaximumValueError ) | ( MinimumLengthError ) | ( MinimumValueError ); diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts index 64ccc29373..0b6e993df1 100644 --- a/tests/resolvers/Query/directChatById.spec.ts +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -7,10 +7,10 @@ import { directChatById as directChatByIdResolver } from "../../../src/resolvers 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 { createTestDirectChat } from "../../helpers/directChat"; import type { TestDirectChatType } from "../../helpers/directChat"; -let testDirectChat: TestDirectChatType +let testDirectChat: TestDirectChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { @@ -48,7 +48,9 @@ describe("resolvers -> Query -> directChatsById", () => { {}, ); - const directChatsByUserId = await DirectChat.findById(testDirectChat?._id).lean(); + const directChatsByUserId = await DirectChat.findById( + testDirectChat?._id, + ).lean(); console.log(directChatsByUserIdPayload); console.log(directChatsByUserId); expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); diff --git a/tests/resolvers/Query/groupChatById.spec.ts b/tests/resolvers/Query/groupChatById.spec.ts new file mode 100644 index 0000000000..d126fa4ac2 --- /dev/null +++ b/tests/resolvers/Query/groupChatById.spec.ts @@ -0,0 +1,58 @@ +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 } 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: QueryGroupChatByIdArgs = { + id: testGroupChat?._id, + }; + + 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 new file mode 100644 index 0000000000..7189529b8f --- /dev/null +++ b/tests/resolvers/Query/groupChatsByUserId.spec.ts @@ -0,0 +1,58 @@ +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 { DirectChat } 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 -> directChatsByUserID", () => { + it(`throws NotFoundError if no directChats exists with directChats.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("GroupChats not found"); + } + }); + + it(`returns list of all directChats with directChat.users containing the user + with _id === args.id`, async () => { + const args: QueryGroupChatsByUserIdArgs = { + id: testUser?._id, + }; + + const groupChatsByUserIdPayload = await groupChatsByUserIdResolver?.( + {}, + args, + {}, + ); + + const groupChatsByUserId = await DirectChat.find({ + users: testUser?._id, + }).lean(); + + expect(groupChatsByUserIdPayload).toEqual(groupChatsByUserId); + }); +}); From 9576d4a2ebb6cda837dd29a4c6c7bed4397ce8dd Mon Sep 17 00:00:00 2001 From: Disha Date: Thu, 18 Jul 2024 22:54:37 +0530 Subject: [PATCH 19/50] fix: test cases --- tests/helpers/directChat.ts | 2 +- tests/helpers/groupChat.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts index 96d8888e78..0b4d523b23 100644 --- a/tests/helpers/directChat.ts +++ b/tests/helpers/directChat.ts @@ -9,7 +9,7 @@ import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; export type TestDirectChatType = - | (InterfaceDirectChat & Document) + | (InterfaceDirectChat & Document) | null; export type TestDirectChatMessageType = diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts index a7a53b96b9..a41591c962 100644 --- a/tests/helpers/groupChat.ts +++ b/tests/helpers/groupChat.ts @@ -9,7 +9,7 @@ import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; export type TestGroupChatType = - | (InterfaceGroupChat & Document) + | (InterfaceGroupChat & Document) | null; export type TestGroupChatMessageType = From c2af22db78ed3d5d5c727583dbb9fa6a68cf44b6 Mon Sep 17 00:00:00 2001 From: Disha Date: Thu, 18 Jul 2024 23:15:44 +0530 Subject: [PATCH 20/50] fix: tests --- tests/resolvers/Query/groupChatById.spec.ts | 7 +++++-- tests/resolvers/Query/groupChatsByUserId.spec.ts | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/resolvers/Query/groupChatById.spec.ts b/tests/resolvers/Query/groupChatById.spec.ts index d126fa4ac2..770557a301 100644 --- a/tests/resolvers/Query/groupChatById.spec.ts +++ b/tests/resolvers/Query/groupChatById.spec.ts @@ -5,7 +5,10 @@ import { connect, disconnect } from "../../helpers/db"; import { groupChatById as groupChatByIdResolver } from "../../../src/resolvers/Query/groupChatById"; import { GroupChat } from "../../../src/models"; -import type { QueryGroupChatByIdArgs } from "../../../src/types/generatedGraphQLTypes"; +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"; @@ -38,7 +41,7 @@ describe("resolvers -> Query -> directChatsById", () => { it(`returns list of all directChats with directChat.users containing the user with _id === args.id`, async () => { - const args: QueryGroupChatByIdArgs = { + const args: QueryGroupChatsByUserIdArgs = { id: testGroupChat?._id, }; diff --git a/tests/resolvers/Query/groupChatsByUserId.spec.ts b/tests/resolvers/Query/groupChatsByUserId.spec.ts index 7189529b8f..7026580b17 100644 --- a/tests/resolvers/Query/groupChatsByUserId.spec.ts +++ b/tests/resolvers/Query/groupChatsByUserId.spec.ts @@ -4,7 +4,7 @@ import { Types } from "mongoose"; import { connect, disconnect } from "../../helpers/db"; import { groupChatsByUserId as groupChatsByUserIdResolver } from "../../../src/resolvers/Query/groupChatsByUserId"; -import { DirectChat } from "../../../src/models"; +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"; @@ -23,8 +23,8 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Query -> directChatsByUserID", () => { - it(`throws NotFoundError if no directChats exists with directChats.users +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 = { @@ -33,11 +33,11 @@ describe("resolvers -> Query -> directChatsByUserID", () => { await groupChatsByUserIdResolver?.({}, args, {}); } catch (error: unknown) { - expect((error as Error).message).toEqual("GroupChats not found"); + expect((error as Error).message).toEqual("Group Chats not found"); } }); - it(`returns list of all directChats with directChat.users containing the user + it(`returns list of all groupChats with groupChat.users containing the user with _id === args.id`, async () => { const args: QueryGroupChatsByUserIdArgs = { id: testUser?._id, @@ -49,7 +49,7 @@ describe("resolvers -> Query -> directChatsByUserID", () => { {}, ); - const groupChatsByUserId = await DirectChat.find({ + const groupChatsByUserId = await GroupChat.find({ users: testUser?._id, }).lean(); From ad486197b3122926b244c8a4e2406a1e51d8ddca Mon Sep 17 00:00:00 2001 From: Disha Date: Thu, 18 Jul 2024 23:45:18 +0530 Subject: [PATCH 21/50] fix test cases --- .../Subscription/messageSentToDirectChat.ts | 6 +- src/types/generatedGraphQLTypes.ts | 4 +- tests/helpers/directChat.ts | 2 +- tests/helpers/groupChat.ts | 2 +- tests/resolvers/Query/directChatById.spec.ts | 19 +++--- tests/resolvers/Query/groupChatById.spec.ts | 61 +++++++++++++++++++ .../Query/groupChatsByUserId.spec.ts | 58 ++++++++++++++++++ 7 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 tests/resolvers/Query/groupChatById.spec.ts create mode 100644 tests/resolvers/Query/groupChatsByUserId.spec.ts diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts index 5dc5355a5e..55ce56e603 100644 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ b/src/resolvers/Subscription/messageSentToDirectChat.ts @@ -6,7 +6,11 @@ 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()); + console.log( + currentUserId, + payload.messageSentToDirectChat.receiver.toString(), + payload.messageSentToDirectChat.sender.toString(), + ); return ( currentUserId === payload.messageSentToDirectChat.receiver.toString() || currentUserId === payload.messageSentToDirectChat.sender.toString() diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 4c05807c81..70954162f5 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -3231,7 +3231,7 @@ export type DirectiveResolverFn TResult | Promise; /** Mapping of union types */ -export type ResolversUnionTypes<_RefType extends Record> = { +export type ResolversUnionTypes> = { ConnectionError: ( InvalidCursor ) | ( MaximumValueError ); CreateAdminError: ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); CreateCommentError: ( PostNotFoundError ); @@ -3240,7 +3240,7 @@ export type ResolversUnionTypes<_RefType extends Record> = { }; /** Mapping of interface types */ -export type ResolversInterfaceTypes<_RefType extends Record> = { +export type ResolversInterfaceTypes> = { ConnectionPageInfo: ( DefaultConnectionPageInfo ); Error: ( MemberNotFoundError ) | ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( PostNotFoundError ) | ( UnauthenticatedError ) | ( UnauthorizedError ) | ( UserNotAuthorizedAdminError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); FieldError: ( InvalidCursor ) | ( MaximumLengthError ) | ( MaximumValueError ) | ( MinimumLengthError ) | ( MinimumValueError ); diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts index 96d8888e78..0b4d523b23 100644 --- a/tests/helpers/directChat.ts +++ b/tests/helpers/directChat.ts @@ -9,7 +9,7 @@ import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; export type TestDirectChatType = - | (InterfaceDirectChat & Document) + | (InterfaceDirectChat & Document) | null; export type TestDirectChatMessageType = diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts index a7a53b96b9..a41591c962 100644 --- a/tests/helpers/groupChat.ts +++ b/tests/helpers/groupChat.ts @@ -9,7 +9,7 @@ import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; export type TestGroupChatType = - | (InterfaceGroupChat & Document) + | (InterfaceGroupChat & Document) | null; export type TestGroupChatMessageType = diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts index f485f49deb..0b6e993df1 100644 --- a/tests/resolvers/Query/directChatById.spec.ts +++ b/tests/resolvers/Query/directChatById.spec.ts @@ -7,17 +7,15 @@ import { directChatById as directChatByIdResolver } from "../../../src/resolvers import { DirectChat } from "../../../src/models"; import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat, TestDirectChatType} from "../../helpers/directChat"; -import type { TestUserType, } from "../../helpers/userAndOrg"; +import { createTestDirectChat } from "../../helpers/directChat"; +import type { TestDirectChatType } from "../../helpers/directChat"; -let testUser: TestUserType; -let testDirectChat: TestDirectChatType +let testDirectChat: TestDirectChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); const resultArray = await createTestDirectChat(); - testUser = resultArray[0]; testDirectChat = resultArray[2]; }); @@ -34,7 +32,7 @@ describe("resolvers -> Query -> directChatsById", () => { await directChatByIdResolver?.({}, args, {}); } catch (error: unknown) { - expect((error as Error).message).toEqual("DirectChats not found"); + expect((error as Error).message).toEqual("Chat not found"); } }); @@ -50,10 +48,11 @@ describe("resolvers -> Query -> directChatsById", () => { {}, ); - const directChatsByUserId = await DirectChat.find({ - users: testDirectChat?._id, - }).lean(); - + const directChatsByUserId = await DirectChat.findById( + testDirectChat?._id, + ).lean(); + console.log(directChatsByUserIdPayload); + console.log(directChatsByUserId); expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); }); }); diff --git a/tests/resolvers/Query/groupChatById.spec.ts b/tests/resolvers/Query/groupChatById.spec.ts new file mode 100644 index 0000000000..770557a301 --- /dev/null +++ b/tests/resolvers/Query/groupChatById.spec.ts @@ -0,0 +1,61 @@ +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, + }; + + 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 new file mode 100644 index 0000000000..7026580b17 --- /dev/null +++ b/tests/resolvers/Query/groupChatsByUserId.spec.ts @@ -0,0 +1,58 @@ +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); + }); +}); From d18843a53d001fc6ec1579109b01f825ac389c41 Mon Sep 17 00:00:00 2001 From: Disha Date: Wed, 24 Jul 2024 21:47:21 +0530 Subject: [PATCH 22/50] added support to reply to direct chat and group chat --- schema.graphql | 2 +- src/constants.ts | 7 ++ src/models/DirectChatMessage.ts | 6 ++ src/models/GroupChatMessage.ts | 6 ++ src/resolvers/DirectChatMessage/index.ts | 2 + src/resolvers/DirectChatMessage/replyTo.ts | 32 ++++++++ src/resolvers/GroupChatMessage/index.ts | 2 + src/resolvers/GroupChatMessage/replyTo.ts | 32 ++++++++ .../Mutation/sendMessageToDirectChat.ts | 3 +- .../Mutation/sendMessageToGroupChat.ts | 1 + src/typeDefs/mutations.ts | 2 + src/typeDefs/types.ts | 2 + src/types/generatedGraphQLTypes.ts | 6 ++ tests/helpers/directChat.ts | 3 + tests/helpers/groupChat.ts | 17 +++++ .../DirectChatMessage/replyTo.spec.ts | 75 +++++++++++++++++++ .../GroupChatMessage/replyTo.spec.ts | 65 ++++++++++++++++ 17 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 src/resolvers/DirectChatMessage/replyTo.ts create mode 100644 src/resolvers/GroupChatMessage/replyTo.ts create mode 100644 tests/resolvers/DirectChatMessage/replyTo.spec.ts create mode 100644 tests/resolvers/GroupChatMessage/replyTo.spec.ts diff --git a/schema.graphql b/schema.graphql index 3a2866bf82..16e2668f87 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1144,7 +1144,7 @@ type Mutation { revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! - sendMessageToDirectChat(chatId: ID!, messageContent: String!): DirectChatMessage! + sendMessageToDirectChat(chatId: ID!, messageContent: String!, replyTo: ID): DirectChatMessage! sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage! signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! diff --git a/src/constants.ts b/src/constants.ts index fab3f2b12d..306a5984b3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -57,6 +57,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 VENUE_ALREADY_EXISTS_ERROR = Object.freeze({ DESC: "Venue already exists", CODE: "venue.alreadyExists", diff --git a/src/models/DirectChatMessage.ts b/src/models/DirectChatMessage.ts index 54ca87ee8d..883d66028c 100644 --- a/src/models/DirectChatMessage.ts +++ b/src/models/DirectChatMessage.ts @@ -11,6 +11,7 @@ export interface InterfaceDirectChatMessage { directChatMessageBelongsTo: PopulatedDoc; sender: PopulatedDoc; receiver: PopulatedDoc; + replyTo: PopulatedDoc; messageContent: string; status: string; createdAt: Date; @@ -43,6 +44,11 @@ const directChatMessageSchema = new Schema( ref: "User", required: true, }, + replyTo: { + type: Schema.Types.ObjectId, + ref: "DirectChatMessage", + required: false, + }, messageContent: { type: String, required: true, diff --git a/src/models/GroupChatMessage.ts b/src/models/GroupChatMessage.ts index 639196e153..63e4f6986d 100644 --- a/src/models/GroupChatMessage.ts +++ b/src/models/GroupChatMessage.ts @@ -12,6 +12,7 @@ export interface InterfaceGroupChatMessage { sender: PopulatedDoc; createdAt: Date; updatedAt: Date; + replyTo: PopulatedDoc; messageContent: string; status: string; } @@ -36,6 +37,11 @@ const groupChatMessageSchema = new Schema( ref: "User", required: true, }, + replyTo: { + type: Schema.Types.ObjectId, + ref: "GroupChatMessage", + required: false, + }, messageContent: { type: String, required: true, diff --git a/src/resolvers/DirectChatMessage/index.ts b/src/resolvers/DirectChatMessage/index.ts index e42390c4ec..ef46538d39 100644 --- a/src/resolvers/DirectChatMessage/index.ts +++ b/src/resolvers/DirectChatMessage/index.ts @@ -1,10 +1,12 @@ import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; import { directChatMessageBelongsTo } from "./directChatMessageBelongsTo"; import { receiver } from "./receiver"; +import { replyTo } from "./replyTo"; import { sender } from "./sender"; export const DirectChatMessage: DirectChatMessageResolvers = { directChatMessageBelongsTo, receiver, sender, + replyTo }; diff --git a/src/resolvers/DirectChatMessage/replyTo.ts b/src/resolvers/DirectChatMessage/replyTo.ts new file mode 100644 index 0000000000..18cbec4af7 --- /dev/null +++ b/src/resolvers/DirectChatMessage/replyTo.ts @@ -0,0 +1,32 @@ +import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { DirectChatMessage } from "../../models"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the receiver(user) of the Direct 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 replyTo: DirectChatMessageResolvers["replyTo"] = async ( + parent, +) => { + console.log("PARENT ", parent); + if(parent.replyTo) { + const result = await DirectChatMessage.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/GroupChatMessage/index.ts b/src/resolvers/GroupChatMessage/index.ts index b837e04871..698d6075db 100644 --- a/src/resolvers/GroupChatMessage/index.ts +++ b/src/resolvers/GroupChatMessage/index.ts @@ -1,8 +1,10 @@ import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; import { groupChatMessageBelongsTo } from "./groupChatMessageBelongsTo"; +import { replyTo } from "./replyTo"; import { sender } from "./sender"; export const GroupChatMessage: GroupChatMessageResolvers = { groupChatMessageBelongsTo, sender, + replyTo }; diff --git a/src/resolvers/GroupChatMessage/replyTo.ts b/src/resolvers/GroupChatMessage/replyTo.ts new file mode 100644 index 0000000000..dd21386e5e --- /dev/null +++ b/src/resolvers/GroupChatMessage/replyTo.ts @@ -0,0 +1,32 @@ +import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { GroupChatMessage } from "../../models"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the receiver(user) of the Direct 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 replyTo: GroupChatMessageResolvers["replyTo"] = async ( + parent, +) => { + console.log("PARENT ", parent); + if(parent.replyTo) { + const result = await GroupChatMessage.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/Mutation/sendMessageToDirectChat.ts b/src/resolvers/Mutation/sendMessageToDirectChat.ts index 65cbf15f2b..f9691c46a0 100644 --- a/src/resolvers/Mutation/sendMessageToDirectChat.ts +++ b/src/resolvers/Mutation/sendMessageToDirectChat.ts @@ -42,12 +42,13 @@ export const sendMessageToDirectChat: MutationResolvers["sendMessageToDirectChat 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, + replyTo: args.replyTo }); // add createdDirectChatMessage to directChat diff --git a/src/resolvers/Mutation/sendMessageToGroupChat.ts b/src/resolvers/Mutation/sendMessageToGroupChat.ts index 93d9f7d5dd..3e2ffb9afc 100644 --- a/src/resolvers/Mutation/sendMessageToGroupChat.ts +++ b/src/resolvers/Mutation/sendMessageToGroupChat.ts @@ -64,6 +64,7 @@ export const sendMessageToGroupChat: MutationResolvers["sendMessageToGroupChat"] sender: context.userId, createdAt: new Date(), messageContent: args.messageContent, + replyTo: args.replyTo }); // add createdGroupChatMessage to groupChat diff --git a/src/typeDefs/mutations.ts b/src/typeDefs/mutations.ts index c133e8ba9d..6541127d02 100644 --- a/src/typeDefs/mutations.ts +++ b/src/typeDefs/mutations.ts @@ -250,11 +250,13 @@ export const mutations = gql` sendMessageToDirectChat( chatId: ID! messageContent: String! + replyTo: ID ): DirectChatMessage! @auth sendMessageToGroupChat( chatId: ID! messageContent: String! + replyTo: ID ): GroupChatMessage! @auth signUp(data: UserInput!, file: String): AuthData! diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index a3a1b41ffa..091023156a 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -191,6 +191,7 @@ export const types = gql` directChatMessageBelongsTo: DirectChat! sender: User! receiver: User! + replyTo: DirectChatMessage createdAt: DateTime! updatedAt: DateTime! messageContent: String! @@ -385,6 +386,7 @@ export const types = gql` _id: ID! groupChatMessageBelongsTo: GroupChat! sender: User! + replyTo: GroupChatMessage createdAt: DateTime! updatedAt: DateTime! messageContent: String! diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 70954162f5..0026406f21 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -628,6 +628,7 @@ export type DirectChatMessage = { directChatMessageBelongsTo: DirectChat; messageContent: Scalars['String']['output']; receiver: User; + replyTo?: Maybe; sender: User; updatedAt: Scalars['DateTime']['output']; }; @@ -1012,6 +1013,7 @@ export type GroupChatMessage = { createdAt: Scalars['DateTime']['output']; groupChatMessageBelongsTo: GroupChat; messageContent: Scalars['String']['output']; + replyTo?: Maybe; sender: User; updatedAt: Scalars['DateTime']['output']; }; @@ -1751,12 +1753,14 @@ export type MutationSendMembershipRequestArgs = { export type MutationSendMessageToDirectChatArgs = { chatId: Scalars['ID']['input']; messageContent: Scalars['String']['input']; + replyTo?: InputMaybe; }; export type MutationSendMessageToGroupChatArgs = { chatId: Scalars['ID']['input']; messageContent: Scalars['String']['input']; + replyTo?: InputMaybe; }; @@ -3952,6 +3956,7 @@ export type DirectChatMessageResolvers; messageContent?: Resolver; receiver?: Resolver; + replyTo?: Resolver, ParentType, ContextType>; sender?: Resolver; updatedAt?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -4144,6 +4149,7 @@ export type GroupChatMessageResolvers; groupChatMessageBelongsTo?: Resolver; messageContent?: Resolver; + replyTo?: Resolver, ParentType, ContextType>; sender?: Resolver; updatedAt?: Resolver; __isTypeOf?: IsTypeOfResolverFn; diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts index 0b4d523b23..624e05d3ee 100644 --- a/tests/helpers/directChat.ts +++ b/tests/helpers/directChat.ts @@ -45,11 +45,14 @@ export const createTestDirectChatMessage = async (): Promise< const [testUser, testOrganization, testDirectChat] = await createTestDirectChat(); + const directChatMessage = await createDirectChatMessage(testUser?._id, testUser?._id, testDirectChat?._id) + if (testDirectChat && testUser) { const testDirectChatMessage = await DirectChatMessage.create({ directChatMessageBelongsTo: testDirectChat._id, sender: testUser._id, receiver: testUser._id, + replyTo: directChatMessage?._id, messageContent: `msgContent${nanoid().toLowerCase()}`, }); return [testUser, testOrganization, testDirectChat, testDirectChatMessage]; diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts index a41591c962..685ee4076b 100644 --- a/tests/helpers/groupChat.ts +++ b/tests/helpers/groupChat.ts @@ -46,12 +46,15 @@ export const createTestGroupChatMessage = async (): Promise< const [testUser, testOrganization, testGroupChat] = await createTestGroupChat(); + const message = await createGroupChatMessage(testUser?._id, testGroupChat?._id) + if (testGroupChat && testUser) { const testGroupChatMessage = await GroupChatMessage.create({ groupChatMessageBelongsTo: testGroupChat._id, sender: testUser._id, createdAt: new Date(), messageContent: `messageContent${nanoid().toLowerCase()}`, + replyTo: message?._id }); return [testUser, testOrganization, testGroupChat, testGroupChatMessage]; @@ -59,3 +62,17 @@ export const createTestGroupChatMessage = async (): Promise< return [testUser, testOrganization, testGroupChat, null]; } }; + +export const createGroupChatMessage = async ( + senderId: string, + groupChatId: string, +): Promise => { + const directChatMessage = await GroupChatMessage.create({ + groupChatMessageBelongsTo: groupChatId, + sender: senderId, + createdAt: new Date(), + messageContent: `messageContent${nanoid().toLowerCase()}`, + }); + + return directChatMessage; +}; diff --git a/tests/resolvers/DirectChatMessage/replyTo.spec.ts b/tests/resolvers/DirectChatMessage/replyTo.spec.ts new file mode 100644 index 0000000000..7b377236fe --- /dev/null +++ b/tests/resolvers/DirectChatMessage/replyTo.spec.ts @@ -0,0 +1,75 @@ +import "dotenv/config"; +import { replyTo as replyToResolver } from "../../../src/resolvers/DirectChatMessage/replyTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { DirectChatMessage } 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 replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + const replyToPayload = + await replyToResolver(parent, {}, {}); + + const replyTo = await DirectChatMessage.findOne({ + _id: testDirectChatMessage?.replyTo, + }).lean(); + + expect(replyToPayload).toEqual( + replyTo, + ); + }); + 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(), + 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(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + } + }); +}); diff --git a/tests/resolvers/GroupChatMessage/replyTo.spec.ts b/tests/resolvers/GroupChatMessage/replyTo.spec.ts new file mode 100644 index 0000000000..cbb9010370 --- /dev/null +++ b/tests/resolvers/GroupChatMessage/replyTo.spec.ts @@ -0,0 +1,65 @@ +import "dotenv/config"; +import { replyTo as replyToResolver } from "../../../src/resolvers/GroupChatMessage/replyTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import { GroupChatMessage } 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 -> replyTo", () => { + it(`returns groupChatMessageBelongsTo object for parent.groupChatMessageBelongsTo`, async () => { + const parent = testGroupChatMessage?.toObject(); + if (!parent) { + throw new Error("Parent object is undefined."); + } + const replyToPayload = + await replyToResolver?.(parent, {}, {}); + + const replyTo = await GroupChatMessage.findOne({ + _id: testGroupChatMessage?.replyTo, + }).lean(); + + expect(replyToPayload).toEqual(replyTo); + }); + it(`throws NotFoundError if no replyTo exists`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => message); + + const parent = { + ...testGroupChatMessage?.toObject(), + reolyTo: new Types.ObjectId(), // Set to a non-existing ObjectId + }; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + try { + if (replyToResolver) { + // @ts-expect-error - Testing for error + await replyToResolver(parent, {}, {}); + } + } catch (error: unknown) { + expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + } + }); +}); From 84696535ca83627a88e001a73e740aa01826a56c Mon Sep 17 00:00:00 2001 From: Disha Date: Wed, 24 Jul 2024 22:13:34 +0530 Subject: [PATCH 23/50] fix: test cases --- src/resolvers/DirectChatMessage/index.ts | 2 +- src/resolvers/DirectChatMessage/replyTo.ts | 33 ++++++++--------- src/resolvers/GroupChatMessage/index.ts | 2 +- src/resolvers/GroupChatMessage/replyTo.ts | 37 +++++++++---------- .../Mutation/sendMessageToDirectChat.ts | 4 +- .../Mutation/sendMessageToGroupChat.ts | 2 +- tests/helpers/directChat.ts | 6 ++- tests/helpers/groupChat.ts | 13 ++++--- .../DirectChatMessage/replyTo.spec.ts | 13 +++---- .../GroupChatMessage/replyTo.spec.ts | 9 ++--- 10 files changed, 60 insertions(+), 61 deletions(-) diff --git a/src/resolvers/DirectChatMessage/index.ts b/src/resolvers/DirectChatMessage/index.ts index ef46538d39..41c8ee48a1 100644 --- a/src/resolvers/DirectChatMessage/index.ts +++ b/src/resolvers/DirectChatMessage/index.ts @@ -8,5 +8,5 @@ export const DirectChatMessage: DirectChatMessageResolvers = { directChatMessageBelongsTo, receiver, sender, - replyTo + replyTo, }; diff --git a/src/resolvers/DirectChatMessage/replyTo.ts b/src/resolvers/DirectChatMessage/replyTo.ts index 18cbec4af7..a8b0ef773c 100644 --- a/src/resolvers/DirectChatMessage/replyTo.ts +++ b/src/resolvers/DirectChatMessage/replyTo.ts @@ -10,23 +10,22 @@ import { errors, requestContext } from "../../libraries"; export const replyTo: DirectChatMessageResolvers["replyTo"] = async ( parent, ) => { - console.log("PARENT ", parent); - if(parent.replyTo) { - const result = await DirectChatMessage.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, - ); - } + console.log("PARENT ", parent); + if (parent.replyTo) { + const result = await DirectChatMessage.findOne({ + _id: parent.replyTo, + }).lean(); + + if (result) { + return result; } else { - return null; + 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/GroupChatMessage/index.ts b/src/resolvers/GroupChatMessage/index.ts index 698d6075db..9419e428eb 100644 --- a/src/resolvers/GroupChatMessage/index.ts +++ b/src/resolvers/GroupChatMessage/index.ts @@ -6,5 +6,5 @@ import { sender } from "./sender"; export const GroupChatMessage: GroupChatMessageResolvers = { groupChatMessageBelongsTo, sender, - replyTo + replyTo, }; diff --git a/src/resolvers/GroupChatMessage/replyTo.ts b/src/resolvers/GroupChatMessage/replyTo.ts index dd21386e5e..62d74c4297 100644 --- a/src/resolvers/GroupChatMessage/replyTo.ts +++ b/src/resolvers/GroupChatMessage/replyTo.ts @@ -7,26 +7,23 @@ import { errors, requestContext } from "../../libraries"; * @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 replyTo: GroupChatMessageResolvers["replyTo"] = async ( - parent, -) => { - console.log("PARENT ", parent); - if(parent.replyTo) { - const result = await GroupChatMessage.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, - ); - } +export const replyTo: GroupChatMessageResolvers["replyTo"] = async (parent) => { + console.log("PARENT ", parent); + if (parent.replyTo) { + const result = await GroupChatMessage.findOne({ + _id: parent.replyTo, + }).lean(); + + if (result) { + return result; } else { - return null; + 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/Mutation/sendMessageToDirectChat.ts b/src/resolvers/Mutation/sendMessageToDirectChat.ts index f9691c46a0..22d1017e6f 100644 --- a/src/resolvers/Mutation/sendMessageToDirectChat.ts +++ b/src/resolvers/Mutation/sendMessageToDirectChat.ts @@ -42,13 +42,13 @@ export const sendMessageToDirectChat: MutationResolvers["sendMessageToDirectChat 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, - replyTo: args.replyTo + replyTo: args.replyTo, }); // add createdDirectChatMessage to directChat diff --git a/src/resolvers/Mutation/sendMessageToGroupChat.ts b/src/resolvers/Mutation/sendMessageToGroupChat.ts index 3e2ffb9afc..7592b51c96 100644 --- a/src/resolvers/Mutation/sendMessageToGroupChat.ts +++ b/src/resolvers/Mutation/sendMessageToGroupChat.ts @@ -64,7 +64,7 @@ export const sendMessageToGroupChat: MutationResolvers["sendMessageToGroupChat"] sender: context.userId, createdAt: new Date(), messageContent: args.messageContent, - replyTo: args.replyTo + replyTo: args.replyTo, }); // add createdGroupChatMessage to groupChat diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts index 624e05d3ee..cf4e852500 100644 --- a/tests/helpers/directChat.ts +++ b/tests/helpers/directChat.ts @@ -45,7 +45,11 @@ export const createTestDirectChatMessage = async (): Promise< const [testUser, testOrganization, testDirectChat] = await createTestDirectChat(); - const directChatMessage = await createDirectChatMessage(testUser?._id, testUser?._id, testDirectChat?._id) + const directChatMessage = await createDirectChatMessage( + testUser?._id, + testUser?._id, + testDirectChat?._id, + ); if (testDirectChat && testUser) { const testDirectChatMessage = await DirectChatMessage.create({ diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts index 685ee4076b..5e9d311f2b 100644 --- a/tests/helpers/groupChat.ts +++ b/tests/helpers/groupChat.ts @@ -46,7 +46,10 @@ export const createTestGroupChatMessage = async (): Promise< const [testUser, testOrganization, testGroupChat] = await createTestGroupChat(); - const message = await createGroupChatMessage(testUser?._id, testGroupChat?._id) + const message = await createGroupChatMessage( + testUser?._id, + testGroupChat?._id, + ); if (testGroupChat && testUser) { const testGroupChatMessage = await GroupChatMessage.create({ @@ -54,7 +57,7 @@ export const createTestGroupChatMessage = async (): Promise< sender: testUser._id, createdAt: new Date(), messageContent: `messageContent${nanoid().toLowerCase()}`, - replyTo: message?._id + replyTo: message?._id, }); return [testUser, testOrganization, testGroupChat, testGroupChatMessage]; @@ -69,9 +72,9 @@ export const createGroupChatMessage = async ( ): Promise => { const directChatMessage = await GroupChatMessage.create({ groupChatMessageBelongsTo: groupChatId, - sender: senderId, - createdAt: new Date(), - messageContent: `messageContent${nanoid().toLowerCase()}`, + sender: senderId, + createdAt: new Date(), + messageContent: `messageContent${nanoid().toLowerCase()}`, }); return directChatMessage; diff --git a/tests/resolvers/DirectChatMessage/replyTo.spec.ts b/tests/resolvers/DirectChatMessage/replyTo.spec.ts index 7b377236fe..163a2a7874 100644 --- a/tests/resolvers/DirectChatMessage/replyTo.spec.ts +++ b/tests/resolvers/DirectChatMessage/replyTo.spec.ts @@ -7,7 +7,7 @@ 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"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../../src/constants"; let testDirectChatMessage: TestDirectChatMessageType; let MONGOOSE_INSTANCE: typeof mongoose; @@ -34,16 +34,13 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { throw new Error("replyToResolver is not a function."); } - const replyToPayload = - await replyToResolver(parent, {}, {}); + const replyToPayload = await replyToResolver(parent, {}, {}); const replyTo = await DirectChatMessage.findOne({ _id: testDirectChatMessage?.replyTo, }).lean(); - expect(replyToPayload).toEqual( - replyTo, - ); + expect(replyToPayload).toEqual(replyTo); }); it(`throws NotFoundError if no directChat exists`, async () => { const { requestContext } = await import("../../../src/libraries"); @@ -68,8 +65,8 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { // @ts-expect-error - Testing for error await replyToResolver(parent, {}, {}); } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect(spy).toBeCalledWith(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(MESSAGE_NOT_FOUND_ERROR.MESSAGE); } }); }); diff --git a/tests/resolvers/GroupChatMessage/replyTo.spec.ts b/tests/resolvers/GroupChatMessage/replyTo.spec.ts index cbb9010370..908f2af1a3 100644 --- a/tests/resolvers/GroupChatMessage/replyTo.spec.ts +++ b/tests/resolvers/GroupChatMessage/replyTo.spec.ts @@ -7,7 +7,7 @@ import { GroupChatMessage } 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"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../../src/constants"; let testGroupChatMessage: TestGroupChatMessageType; let MONGOOSE_INSTANCE: typeof mongoose; @@ -28,8 +28,7 @@ describe("resolvers -> GroupChatMessage -> replyTo", () => { if (!parent) { throw new Error("Parent object is undefined."); } - const replyToPayload = - await replyToResolver?.(parent, {}, {}); + const replyToPayload = await replyToResolver?.(parent, {}, {}); const replyTo = await GroupChatMessage.findOne({ _id: testGroupChatMessage?.replyTo, @@ -58,8 +57,8 @@ describe("resolvers -> GroupChatMessage -> replyTo", () => { await replyToResolver(parent, {}, {}); } } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect(spy).toBeCalledWith(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(MESSAGE_NOT_FOUND_ERROR.MESSAGE); } }); }); From 87ad70f0df2e3b83ae1d3b7e10ce5f3813c60dcb Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 28 Jul 2024 16:29:45 +0530 Subject: [PATCH 24/50] updated schema for chat --- codegen.ts | 4 + docker-compose.dev.yaml | 2 +- schema.graphql | 39 ++++++ src/models/Chat.ts | 116 +++++++++++++++++ src/models/ChatMessage.ts | 97 ++++++++++++++ src/models/index.ts | 2 + src/resolvers/Chat/admins.ts | 14 ++ src/resolvers/Chat/creator.ts | 12 ++ src/resolvers/Chat/index.ts | 14 ++ src/resolvers/Chat/messages.ts | 14 ++ src/resolvers/Chat/organization.ts | 26 ++++ src/resolvers/Chat/users.ts | 14 ++ .../ChatMessage/chatMessageBelongsTo.ts | 25 ++++ src/resolvers/ChatMessage/index.ts | 10 ++ src/resolvers/ChatMessage/replyTo.ts | 28 ++++ src/resolvers/ChatMessage/sender.ts | 24 ++++ src/resolvers/Mutation/createChat.ts | 92 ++++++++++++++ src/resolvers/Mutation/index.ts | 6 +- src/resolvers/Mutation/sendMessageToChat.ts | 74 +++++++++++ src/resolvers/Query/chatById.ts | 26 ++++ src/resolvers/Query/chatsByUserId.ts | 23 ++++ src/resolvers/Query/index.ts | 4 + src/resolvers/Subscription/index.ts | 2 + .../Subscription/messageSentToChat.ts | 44 +++++++ src/resolvers/index.ts | 5 + src/typeDefs/inputs.ts | 7 +- src/typeDefs/mutations.ts | 9 +- src/typeDefs/queries.ts | 4 + src/typeDefs/subscriptions.ts | 1 + src/typeDefs/types.ts | 27 ++++ src/types/generatedGraphQLTypes.ts | 120 ++++++++++++++++-- 31 files changed, 869 insertions(+), 16 deletions(-) create mode 100644 src/models/Chat.ts create mode 100644 src/models/ChatMessage.ts create mode 100644 src/resolvers/Chat/admins.ts create mode 100644 src/resolvers/Chat/creator.ts create mode 100644 src/resolvers/Chat/index.ts create mode 100644 src/resolvers/Chat/messages.ts create mode 100644 src/resolvers/Chat/organization.ts create mode 100644 src/resolvers/Chat/users.ts create mode 100644 src/resolvers/ChatMessage/chatMessageBelongsTo.ts create mode 100644 src/resolvers/ChatMessage/index.ts create mode 100644 src/resolvers/ChatMessage/replyTo.ts create mode 100644 src/resolvers/ChatMessage/sender.ts create mode 100644 src/resolvers/Mutation/createChat.ts create mode 100644 src/resolvers/Mutation/sendMessageToChat.ts create mode 100644 src/resolvers/Query/chatById.ts create mode 100644 src/resolvers/Query/chatsByUserId.ts create mode 100644 src/resolvers/Subscription/messageSentToChat.ts diff --git a/codegen.ts b/codegen.ts index 75bbf9f1c6..40d5c18d05 100644 --- a/codegen.ts +++ b/codegen.ts @@ -48,6 +48,10 @@ const config: CodegenConfig = { DirectChat: "../models/DirectChat#InterfaceDirectChat", + Chat: "../models/Chat#InterfaceChat", + + ChatMessage: "../models/ChatMessage#InterfaceChatMessage", + DirectChatMessage: "../models/DirectChatMessage#InterfaceDirectChatMessage", diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 02f8cbfa9a..2c0599b401 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -28,7 +28,7 @@ services: - mongodb - redis-stack-server environment: - - MONGO_DB_URL=mongodb://mongodb:27017 + - mongodb+srv://disha:disha@test.hz7knd5.mongodb.net/?retryWrites=true&w=majority&appName=test - REDIS_HOST=redis-stack-server - REDIS_PORT=6379 diff --git a/schema.graphql b/schema.graphql index 16e2668f87..f434dc0b15 100644 --- a/schema.graphql +++ b/schema.graphql @@ -554,6 +554,32 @@ type DirectChatMessage { updatedAt: DateTime! } +type Chat { + _id: ID! + isGroup: Boolean + name: String + createdAt: DateTime! + creator: User + messages: [ChatMessage] + organization: Organization + updatedAt: DateTime! + users: [User!]! + admins: [User] + lastMessageId: String +} + +type ChatMessage { + _id: ID! + createdAt: DateTime! + chatMessageBelongsTo: Chat! + messageContent: String! + type: String! + replyTo: ChatMessage + sender: User! + deletedBy: [User] + updatedAt: DateTime! +} + type Donation { _id: ID! amount: Float! @@ -1075,6 +1101,7 @@ type Mutation { createAgendaSection(input: CreateAgendaSectionInput!): AgendaSection! createComment(data: CommentInput!, postId: ID!): Comment createDirectChat(data: createChatInput!): DirectChat! + createChat(data: chatInput!): Chat createDonation(amount: Float!, nameOfOrg: String!, nameOfUser: String!, orgId: ID!, payPalId: ID!, userId: ID!): Donation! createEvent(data: EventInput!, recurrenceRuleData: RecurrenceRuleInput): Event! createEventVolunteer(data: EventVolunteerInput!): EventVolunteer! @@ -1144,6 +1171,7 @@ type Mutation { revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! + sendMessageToChat(chatId: ID!, messageContent: String!, type: String!, replyTo: ID): ChatMessage! sendMessageToDirectChat(chatId: ID!, messageContent: String!, replyTo: ID): DirectChatMessage! sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage! signUp(data: UserInput!, file: String): AuthData! @@ -1468,6 +1496,8 @@ type Query { checkAuth: User! customDataByOrganization(organizationId: ID!): [UserCustomData!]! customFieldsByOrganization(id: ID!): [OrganizationCustomField] + chatById(id: ID!): Chat! + chatsByUserId(id: ID!): [Chat] directChatsByUserID(id: ID!): [DirectChat] directChatsMessagesByChatID(id: ID!): [DirectChatMessage] directChatById(id: ID!): DirectChat @@ -1598,6 +1628,7 @@ enum Status { type Subscription { directMessageChat: MessageChat messageSentToDirectChat(userId: ID!): DirectChatMessage + messageSentToChat(userId: ID!): ChatMessage messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } @@ -2017,6 +2048,14 @@ input createChatInput { userIds: [ID!]! } +input chatInput { + isGroup: Boolean! + organizationId: ID + userIds: [ID!]! + name: String + image: String +} + type createDirectChatPayload { directChat: DirectChat userErrors: [CreateDirectChatError!]! diff --git a/src/models/Chat.ts b/src/models/Chat.ts new file mode 100644 index 0000000000..fd0c289dba --- /dev/null +++ b/src/models/Chat.ts @@ -0,0 +1,116 @@ +import type { PopulatedDoc, Types, Document, Model } from "mongoose"; +import { Schema, model, models } from "mongoose"; +import type { InterfaceOrganization } from "./Organization"; +import type { InterfaceUser } from "./User"; +import { createLoggingMiddleware } from "../libraries/dbLogger"; +import { InterfaceChatMessage } from "./ChatMessage"; +/** + * Interface representing a document for direct chat in MongoDB. + */ +export interface InterfaceChat { + _id: Types.ObjectId; + isGroup: boolean; + name: String; + users: PopulatedDoc[]; + messages: PopulatedDoc[]; + creatorId: PopulatedDoc; + organization: PopulatedDoc; + status: string; + admins: PopulatedDoc[]; + createdAt: Date; + updatedAt: Date; + lastMessageId: string; +} + +/** + * Mongoose schema for a direct 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 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. + */ +const chatSchema = new Schema( + { + users: [ + { + type: Schema.Types.ObjectId, + ref: "User", + required: true, + }, + ], + isGroup: { + type: Boolean, + required: true, + }, + name: { + type: String, + required: false, + }, + image: { + type: String, + require: false, + }, + messages: [ + { + type: Schema.Types.ObjectId, + ref: "ChatMessage", + }, + ], + creatorId: { + type: Schema.Types.ObjectId, + 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, + }, +); + +// Add logging middleware for directChatSchema +createLoggingMiddleware(chatSchema, "Chat"); + +/** + * Retrieves or creates the Mongoose model for DirectChat. + * Prevents Mongoose OverwriteModelError during testing. + */ +const chatModel = (): Model => + model("Chat", chatSchema); + +// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. +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..f4a7680b7c --- /dev/null +++ b/src/models/ChatMessage.ts @@ -0,0 +1,97 @@ +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 { InterfaceChat } from "./Chat"; + +/** + * Represents a document for a direct chat message in the MongoDB database. + */ +export interface InterfaceChatMessage { + _id: Types.ObjectId; + chatMessageBelongsTo: PopulatedDoc; + sender: PopulatedDoc; + replyTo: PopulatedDoc; + messageContent: string; + type: string; + status: string; + deletedBy: PopulatedDoc[]; + 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 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, + }, + type: { + type: String, + required: true, + enum: ["STRING", "VIDEO", "IMAGE", "FILE"], + }, + 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/index.ts b/src/models/index.ts index 9ce9aed7e7..bd89ca35f3 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -40,3 +40,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..79b0be4684 --- /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 direct 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 admins: ChatResolvers["users"] = async (parent) => { + return await User.find({ + _id: { + $in: parent.users, + }, + }).lean(); +}; diff --git a/src/resolvers/Chat/creator.ts b/src/resolvers/Chat/creator.ts new file mode 100644 index 0000000000..795752c870 --- /dev/null +++ b/src/resolvers/Chat/creator.ts @@ -0,0 +1,12 @@ +import { User } from "../../models"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the specified Direct 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: ChatResolvers["creator"] = async (parent) => { + return await User.findOne({ + _id: parent.creatorId, + }).lean(); +}; diff --git a/src/resolvers/Chat/index.ts b/src/resolvers/Chat/index.ts new file mode 100644 index 0000000000..d4559ae213 --- /dev/null +++ b/src/resolvers/Chat/index.ts @@ -0,0 +1,14 @@ +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 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..12cb4178ab --- /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 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: ChatResolvers["messages"] = async (parent) => { + return await ChatMessage.find({ + _id: { + $in: parent.messages, + }, + }).lean(); +}; diff --git a/src/resolvers/Chat/organization.ts b/src/resolvers/Chat/organization.ts new file mode 100644 index 0000000000..a3bec56002 --- /dev/null +++ b/src/resolvers/Chat/organization.ts @@ -0,0 +1,26 @@ +import type { InterfaceOrganization } from "../../models"; +import { Organization } from "../../models"; +import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; +import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the Organization for the 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 Organization data. + */ +export const organization: ChatResolvers["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) cacheOrganizations([organization]); + + return organization as InterfaceOrganization; +}; diff --git a/src/resolvers/Chat/users.ts b/src/resolvers/Chat/users.ts new file mode 100644 index 0000000000..00c126838f --- /dev/null +++ b/src/resolvers/Chat/users.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 direct 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: ChatResolvers["users"] = async (parent) => { + return await User.find({ + _id: { + $in: parent.users, + }, + }).lean(); +}; diff --git a/src/resolvers/ChatMessage/chatMessageBelongsTo.ts b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts new file mode 100644 index 0000000000..a41878a671 --- /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 Direct 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 Direct 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..971e59503f --- /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 receiver(user) of the Direct 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 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..8e7280b739 --- /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 Direct 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/Mutation/createChat.ts b/src/resolvers/Mutation/createChat.ts new file mode 100644 index 0000000000..033872bdcd --- /dev/null +++ b/src/resolvers/Mutation/createChat.ts @@ -0,0 +1,92 @@ +import { + ORGANIZATION_NOT_FOUND_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import { Chat, Organization, User } from "../../models"; +import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; +import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This function enables to create a 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 user exists + * 2. If the organization exists + * @returns Created group chat + */ +export const createChat: MutationResolvers["createChat"] = async ( + _parent, + args, + context, +) => { + let organization; + const usersInChat = []; + if (args.data.isGroup && args.data.organizationId) { + 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 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, + ); + } + } + + 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, + ); + } + usersInChat.push(userId); + } + + const now = new Date(); + + const chatPayload = args.data.isGroup + ? { + isGroup: args.data.isGroup, + creatorId: context.userId, + users: usersInChat, + organization: args.data?.organizationId, + name: args.data?.name, + admins: [context.userId], + createdAt: now, + updatedAt: now, + image: args.data.image, + } + : { + creatorId: context.userId, + users: usersInChat, + isGroup: args.data.isGroup, + createdAt: now, + updatedAt: now, + }; + + const createdChat = await Chat.create(chatPayload); + + return createdChat.toObject(); +}; diff --git a/src/resolvers/Mutation/index.ts b/src/resolvers/Mutation/index.ts index 60924ad339..bef02acf23 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -24,7 +24,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"; @@ -91,6 +91,7 @@ import { revokeRefreshTokenForUser } from "./revokeRefreshTokenForUser"; import { saveFcmToken } from "./saveFcmToken"; import { sendMembershipRequest } from "./sendMembershipRequest"; import { sendMessageToDirectChat } from "./sendMessageToDirectChat"; +import { sendMessageToChat } from "./sendMessageToChat"; import { sendMessageToGroupChat } from "./sendMessageToGroupChat"; import { signUp } from "./signUp"; import { togglePostPin } from "./togglePostPin"; @@ -154,7 +155,7 @@ export const Mutation: MutationResolvers = { createAgendaCategory, createAgendaItem, createAgendaSection, - createDirectChat, + createChat, createDonation, createEvent, createFund, @@ -217,6 +218,7 @@ export const Mutation: MutationResolvers = { saveFcmToken, sendMembershipRequest, sendMessageToDirectChat, + sendMessageToChat, sendMessageToGroupChat, signUp, togglePostPin, diff --git a/src/resolvers/Mutation/sendMessageToChat.ts b/src/resolvers/Mutation/sendMessageToChat.ts new file mode 100644 index 0000000000..591cd1bb9e --- /dev/null +++ b/src/resolvers/Mutation/sendMessageToChat.ts @@ -0,0 +1,74 @@ +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 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 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, + type: args.type, + 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/Query/chatById.ts b/src/resolvers/Query/chatById.ts new file mode 100644 index 0000000000..bc79b1e946 --- /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 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 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..23b2f8bb09 --- /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 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 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/index.ts b/src/resolvers/Query/index.ts index 55c74a7bca..6c7a619714 100644 --- a/src/resolvers/Query/index.ts +++ b/src/resolvers/Query/index.ts @@ -16,6 +16,8 @@ import { customFieldsByOrganization } from "./customFieldsByOrganization"; import { directChatsByUserID } from "./directChatsByUserID"; import { directChatsMessagesByChatID } from "./directChatsMessagesByChatID"; import { directChatById } from "./directChatById"; +import { chatById } from "./chatById"; +import { chatsByUserId } from "./chatsByUserId"; import { groupChatById } from "./groupChatById"; import { groupChatsByUserId } from "./groupChatsByUserId"; import { event } from "./event"; @@ -64,6 +66,8 @@ export const Query: QueryResolvers = { getCommunityData, customFieldsByOrganization, customDataByOrganization, + chatById, + chatsByUserId, directChatsByUserID, directChatsMessagesByChatID, directChatById, diff --git a/src/resolvers/Subscription/index.ts b/src/resolvers/Subscription/index.ts index c981720fcb..9e9e380a09 100644 --- a/src/resolvers/Subscription/index.ts +++ b/src/resolvers/Subscription/index.ts @@ -2,10 +2,12 @@ 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..a48a65d0b6 --- /dev/null +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -0,0 +1,44 @@ +import { withFilter } from "graphql-subscriptions"; +import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; + +const MESSAGE_SENT_TO_CHAT = "MESSAGE_SENT_TO_CHAT"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const filterFunction = async function ( + payload: any, + variables: any, +): 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 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 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/index.ts b/src/resolvers/index.ts index 01f58e313a..2267e01ca4 100644 --- a/src/resolvers/index.ts +++ b/src/resolvers/index.ts @@ -19,6 +19,8 @@ import { AgendaSection } from "./AgendaSection"; import { AgendaCategory } from "./AgendaCategory"; import { CheckIn } from "./CheckIn"; import { Comment } from "./Comment"; +import { Chat } from "./Chat"; +import { ChatMessage } from "./ChatMessage"; import { DirectChat } from "./DirectChat"; import { DirectChatMessage } from "./DirectChatMessage"; import { Event } from "./Event"; @@ -52,6 +54,8 @@ const resolvers: Resolvers = { Advertisement, CheckIn, Comment, + Chat, + ChatMessage, DirectChat, DirectChatMessage, Event, @@ -91,6 +95,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 e209e9a09d..f550bbbe0a 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 6541127d02..6d50602cb4 100644 --- a/src/typeDefs/mutations.ts +++ b/src/typeDefs/mutations.ts @@ -87,7 +87,7 @@ export const mutations = gql` createComment(postId: ID!, data: CommentInput!): Comment @auth - createDirectChat(data: createChatInput!): DirectChat! @auth + createChat(data: chatInput!): Chat createDonation( userId: ID! @@ -253,6 +253,13 @@ export const mutations = gql` replyTo: ID ): DirectChatMessage! @auth + sendMessageToChat( + chatId: ID! + messageContent: String! + type: String! + replyTo: ID + ): ChatMessage! @auth + sendMessageToGroupChat( chatId: ID! messageContent: String! diff --git a/src/typeDefs/queries.ts b/src/typeDefs/queries.ts index 80f0c4acaa..79cc7787a6 100644 --- a/src/typeDefs/queries.ts +++ b/src/typeDefs/queries.ts @@ -41,6 +41,10 @@ export const queries = gql` customDataByOrganization(organizationId: ID!): [UserCustomData!]! + chatById(id: ID!): Chat! + + chatsByUserId(id: ID!): [Chat] + directChatsByUserID(id: ID!): [DirectChat] directChatById(id: ID!): DirectChat diff --git a/src/typeDefs/subscriptions.ts b/src/typeDefs/subscriptions.ts index 4c718b9761..45bc014656 100644 --- a/src/typeDefs/subscriptions.ts +++ b/src/typeDefs/subscriptions.ts @@ -5,6 +5,7 @@ export const subscriptions = gql` type Subscription { directMessageChat: MessageChat messageSentToDirectChat(userId: ID!): DirectChatMessage + messageSentToChat(userId: ID!): ChatMessage messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index 091023156a..7fcf81d2df 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -767,4 +767,31 @@ 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! + type: String! + sender: User! + deletedBy: [User] + updatedAt: DateTime! + } `; diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 0026406f21..f281e86b54 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -11,6 +11,8 @@ import type { InterfaceMessageChat as InterfaceMessageChatModel } from '../model 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 { InterfaceChat as InterfaceChatModel } from '../models/Chat'; +import type { InterfaceChatMessage as InterfaceChatMessageModel } from '../models/ChatMessage'; import type { InterfaceDirectChatMessage as InterfaceDirectChatMessageModel } from '../models/DirectChatMessage'; import type { InterfaceDonation as InterfaceDonationModel } from '../models/Donation'; import type { InterfaceEvent as InterfaceEventModel } from '../models/Event'; @@ -250,6 +252,35 @@ export type CampaignWhereInput = { name_contains?: 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; + type: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; +}; + export type CheckIn = { __typename?: 'CheckIn'; _id: Scalars['ID']['output']; @@ -1166,8 +1197,8 @@ export type Mutation = { createAgendaCategory: AgendaCategory; createAgendaItem: AgendaItem; createAgendaSection: AgendaSection; + createChat?: Maybe; createComment?: Maybe; - createDirectChat: DirectChat; createDonation: Donation; createEvent: Event; createEventVolunteer: EventVolunteer; @@ -1237,6 +1268,7 @@ export type Mutation = { revokeRefreshTokenForUser: Scalars['Boolean']['output']; saveFcmToken: Scalars['Boolean']['output']; sendMembershipRequest: MembershipRequest; + sendMessageToChat: ChatMessage; sendMessageToDirectChat: DirectChatMessage; sendMessageToGroupChat: GroupChatMessage; signUp: AuthData; @@ -1408,14 +1440,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']; }; @@ -1750,6 +1782,14 @@ export type MutationSendMembershipRequestArgs = { }; +export type MutationSendMessageToChatArgs = { + chatId: Scalars['ID']['input']; + messageContent: Scalars['String']['input']; + replyTo?: InputMaybe; + type: Scalars['String']['input']; +}; + + export type MutationSendMessageToDirectChatArgs = { chatId: Scalars['ID']['input']; messageContent: Scalars['String']['input']; @@ -2261,6 +2301,8 @@ export type Query = { agendaItemByEvent?: Maybe>>; agendaItemByOrganization?: Maybe>>; agendaItemCategoriesByOrganization?: Maybe>>; + chatById: Chat; + chatsByUserId?: Maybe>>; checkAuth: User; customDataByOrganization: Array; customFieldsByOrganization?: Maybe>>; @@ -2362,6 +2404,16 @@ export type QueryAgendaItemCategoriesByOrganizationArgs = { }; +export type QueryChatByIdArgs = { + id: Scalars['ID']['input']; +}; + + +export type QueryChatsByUserIdArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryCustomDataByOrganizationArgs = { organizationId: Scalars['ID']['input']; }; @@ -2688,12 +2740,18 @@ export type Status = export type Subscription = { __typename?: 'Subscription'; directMessageChat?: Maybe; + messageSentToChat?: Maybe; messageSentToDirectChat?: Maybe; messageSentToGroupChat?: Maybe; onPluginUpdate?: Maybe; }; +export type SubscriptionMessageSentToChatArgs = { + userId: Scalars['ID']['input']; +}; + + export type SubscriptionMessageSentToDirectChatArgs = { userId: Scalars['ID']['input']; }; @@ -3149,7 +3207,10 @@ export type WeekDays = | 'TUESDAY' | 'WEDNESDAY'; -export type CreateChatInput = { +export type ChatInput = { + image?: InputMaybe; + isGroup: Scalars['Boolean']['input']; + name?: InputMaybe; organizationId?: InputMaybe; userIds: Array; }; @@ -3273,6 +3334,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'] }>; @@ -3458,7 +3521,7 @@ export type ResolversTypes = { VenueOrderByInput: VenueOrderByInput; VenueWhereInput: VenueWhereInput; WeekDays: WeekDays; - createChatInput: CreateChatInput; + chatInput: ChatInput; createDirectChatPayload: ResolverTypeWrapper & { directChat?: Maybe, userErrors: Array }>; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; @@ -3484,6 +3547,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'] }; @@ -3647,7 +3712,7 @@ export type ResolversParentTypes = { Venue: InterfaceVenueModel; VenueInput: VenueInput; VenueWhereInput: VenueWhereInput; - createChatInput: CreateChatInput; + chatInput: ChatInput; createDirectChatPayload: Omit & { directChat?: Maybe, userErrors: Array }; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; @@ -3810,6 +3875,35 @@ 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; + type?: Resolver; + updatedAt?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type CheckInResolvers = { _id?: Resolver; createdAt?: Resolver; @@ -4276,8 +4370,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>; @@ -4347,6 +4441,7 @@ export type MutationResolvers; saveFcmToken?: Resolver>; sendMembershipRequest?: Resolver>; + sendMessageToChat?: Resolver>; sendMessageToDirectChat?: Resolver>; sendMessageToGroupChat?: Resolver>; signUp?: Resolver>; @@ -4535,6 +4630,8 @@ 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>; @@ -4614,6 +4711,7 @@ export type SocialMediaUrlsResolvers = { directMessageChat?: SubscriptionResolver, "directMessageChat", ParentType, ContextType>; + messageSentToChat?: SubscriptionResolver, "messageSentToChat", ParentType, ContextType, RequireFields>; messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType, RequireFields>; messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType, RequireFields>; onPluginUpdate?: SubscriptionResolver, "onPluginUpdate", ParentType, ContextType>; @@ -4799,6 +4897,8 @@ export type Resolvers = { Any?: GraphQLScalarType; AppUserProfile?: AppUserProfileResolvers; AuthData?: AuthDataResolvers; + Chat?: ChatResolvers; + ChatMessage?: ChatMessageResolvers; CheckIn?: CheckInResolvers; CheckInStatus?: CheckInStatusResolvers; CheckOut?: CheckOutResolvers; From 33535acd86cc6943c567ec20c446f4bee6efb0ea Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 00:04:51 +0530 Subject: [PATCH 25/50] Added tests for chat --- src/resolvers/DirectChatMessage/replyTo.ts | 1 - src/resolvers/Mutation/createDirectChat.ts | 49 -------- tests/helpers/chat.ts | 109 ++++++++++++++++++ tests/resolvers/Chat/admins.spec.ts | 0 .../{DirectChat => Chat}/creator.spec.ts | 16 +-- .../{DirectChat => Chat}/messages.spec.ts | 22 ++-- tests/resolvers/Chat/organization.spec.ts | 0 .../{DirectChat => Chat}/users.spec.ts | 16 +-- .../chatMessageBelongsTo.ts} | 36 +++--- .../replyTo.ts} | 22 ++-- .../sender.spec.ts | 18 +-- .../resolvers/DirectChat/organization.spec.ts | 53 --------- .../DirectChatMessage/receiver.spec.ts | 64 ---------- ...eDirectChat.spec.ts => createChat.spec.ts} | 33 +++--- .../Subscription/messageSentToChat.spec.ts | 100 ++++++++++++++++ 15 files changed, 292 insertions(+), 247 deletions(-) delete mode 100644 src/resolvers/Mutation/createDirectChat.ts create mode 100644 tests/helpers/chat.ts create mode 100644 tests/resolvers/Chat/admins.spec.ts rename tests/resolvers/{DirectChat => Chat}/creator.spec.ts (69%) rename tests/resolvers/{DirectChat => Chat}/messages.spec.ts (57%) create mode 100644 tests/resolvers/Chat/organization.spec.ts rename tests/resolvers/{DirectChat => Chat}/users.spec.ts (66%) rename tests/resolvers/{DirectChatMessage/directChatMessageBelongsTo.spec.ts => ChatMessage/chatMessageBelongsTo.ts} (59%) rename tests/resolvers/{DirectChatMessage/replyTo.spec.ts => ChatMessage/replyTo.ts} (76%) rename tests/resolvers/{DirectChatMessage => ChatMessage}/sender.spec.ts (78%) delete mode 100644 tests/resolvers/DirectChat/organization.spec.ts delete mode 100644 tests/resolvers/DirectChatMessage/receiver.spec.ts rename tests/resolvers/Mutation/{createDirectChat.spec.ts => createChat.spec.ts} (74%) create mode 100644 tests/resolvers/Subscription/messageSentToChat.spec.ts diff --git a/src/resolvers/DirectChatMessage/replyTo.ts b/src/resolvers/DirectChatMessage/replyTo.ts index a8b0ef773c..bcc6ee9f1a 100644 --- a/src/resolvers/DirectChatMessage/replyTo.ts +++ b/src/resolvers/DirectChatMessage/replyTo.ts @@ -10,7 +10,6 @@ import { errors, requestContext } from "../../libraries"; export const replyTo: DirectChatMessageResolvers["replyTo"] = async ( parent, ) => { - console.log("PARENT ", parent); if (parent.replyTo) { const result = await DirectChatMessage.findOne({ _id: parent.replyTo, diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts deleted file mode 100644 index 3d0438564c..0000000000 --- a/src/resolvers/Mutation/createDirectChat.ts +++ /dev/null @@ -1,49 +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"; -/** - * This function enables to create 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 user exists - * @returns Created 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/tests/helpers/chat.ts b/tests/helpers/chat.ts new file mode 100644 index 0000000000..caee724332 --- /dev/null +++ b/tests/helpers/chat.ts @@ -0,0 +1,109 @@ +import { nanoid } from "nanoid"; +import type { + InterfaceChat, + InterfaceChatMessage, +} from "../../src/models"; +import { Chat, ChatMessage, DirectChat, DirectChatMessage } 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, + }); + + return [testUser, testOrganization, testChat]; + } else { + return [testUser, testOrganization, null]; + } +}; + +export const createTestChatMessage = async (): Promise< + [ + TestUserType, + TestOrganizationType, + TestChatType, + TestChatMessageType, + ] +> => { + const [testUser, testOrganization, testChat] = + await createTestChat(); + + const chatMessage = await createChatMessage( + testUser?._id, + testChat?._id, + ); + + if (testChat && testUser) { + const testChatMessage = await ChatMessage.create({ + directChatMessageBelongsTo: testChat._id, + sender: testUser._id, + replyTo: chatMessage?._id, + messageContent: `msgContent${nanoid().toLowerCase()}`, + }); + 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()}`, + }); + + return testChat; +}; + +export const createTestChatwithUsers = async ( + creator: string, + organizationId: string, + users: string[], +): Promise => { + const testChat = await Chat.create({ + creatorId: creator, + users: users, + organization: organizationId, + }); + return testChat; +}; + +export const createChatMessage = async ( + senderId: string, + directChatId: string, +): Promise => { + const chatMessage = await ChatMessage.create({ + chatMessageBelongsTo: directChatId, + sender: senderId, + messageContent: `messageContent${nanoid().toLowerCase()}`, + }); + + return chatMessage; +}; diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts new file mode 100644 index 0000000000..e69de29bb2 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/Chat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/resolvers/DirectChat/users.spec.ts b/tests/resolvers/Chat/users.spec.ts similarity index 66% rename from tests/resolvers/DirectChat/users.spec.ts rename to tests/resolvers/Chat/users.spec.ts index d30e6fa4cd..06ca8e3ada 100644 --- a/tests/resolvers/DirectChat/users.spec.ts +++ b/tests/resolvers/Chat/users.spec.ts @@ -4,25 +4,25 @@ 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/DirectChatMessage/directChatMessageBelongsTo.spec.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts similarity index 59% rename from tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts rename to tests/resolvers/ChatMessage/chatMessageBelongsTo.ts index 5ff19d843e..fb0140edf7 100644 --- a/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts @@ -1,21 +1,21 @@ import "dotenv/config"; -import { directChatMessageBelongsTo as directChatMessageBelongsToResolver } from "../../../src/resolvers/DirectChatMessage/directChatMessageBelongsTo"; +import { chatMessageBelongsTo as chatMessageBelongsToResolver } from "../../../src/resolvers/ChatMessage/chatMessageBelongsTo"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { DirectChat } from "../../../src/models"; +import { Chat } 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 { CHAT_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,25 +24,25 @@ afterAll(async () => { describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { - const parent = testDirectChatMessage?.toObject(); + const parent = testChatMessage?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } - if (typeof directChatMessageBelongsToResolver !== "function") { + if (typeof chatMessageBelongsToResolver !== "function") { throw new Error("directChatMessageBelongsToResolver is not a function."); } - const directChatMessageBelongsToPayload = - await directChatMessageBelongsToResolver(parent, {}, {}); + const chatMessageBelongsToPayload = + await chatMessageBelongsToResolver(parent, {}, {}); - const directChatMessageBelongsTo = await DirectChat.findOne({ - _id: testDirectChatMessage?.directChatMessageBelongsTo, + const chatMessageBelongsTo = await Chat.findOne({ + _id: testChatMessage?.chatMessageBelongsTo, }).lean(); - expect(directChatMessageBelongsToPayload).toEqual( - directChatMessageBelongsTo, + expect(chatMessageBelongsToPayload).toEqual( + chatMessageBelongsTo, ); }); it(`throws NotFoundError if no directChat exists`, async () => { @@ -52,7 +52,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { .mockImplementationOnce((message) => message); const parent = { - ...testDirectChatMessage?.toObject(), + ...testChatMessage?.toObject(), directChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId }; @@ -60,13 +60,13 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { throw new Error("Parent object is undefined."); } - if (typeof directChatMessageBelongsToResolver !== "function") { + if (typeof chatMessageBelongsToResolver !== "function") { throw new Error("directChatMessageBelongsToResolver is not a function."); } try { // @ts-expect-error - Testing for error - await directChatMessageBelongsToResolver(parent, {}, {}); + 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/DirectChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.ts similarity index 76% rename from tests/resolvers/DirectChatMessage/replyTo.spec.ts rename to tests/resolvers/ChatMessage/replyTo.ts index 163a2a7874..b720cfe97c 100644 --- a/tests/resolvers/DirectChatMessage/replyTo.spec.ts +++ b/tests/resolvers/ChatMessage/replyTo.ts @@ -1,21 +1,21 @@ import "dotenv/config"; -import { replyTo as replyToResolver } from "../../../src/resolvers/DirectChatMessage/replyTo"; +import { replyTo as replyToResolver } from "../../../src/resolvers/ChatMessage/replyTo"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { DirectChatMessage } from "../../../src/models"; +import { ChatMessage } 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 { MESSAGE_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,7 +24,7 @@ afterAll(async () => { describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { - const parent = testDirectChatMessage?.toObject(); + const parent = testChatMessage?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); @@ -36,8 +36,8 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { const replyToPayload = await replyToResolver(parent, {}, {}); - const replyTo = await DirectChatMessage.findOne({ - _id: testDirectChatMessage?.replyTo, + const replyTo = await ChatMessage.findOne({ + _id: testChatMessage?.replyTo, }).lean(); expect(replyToPayload).toEqual(replyTo); @@ -49,7 +49,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { .mockImplementationOnce((message) => message); const parent = { - ...testDirectChatMessage?.toObject(), + ...testChatMessage?.toObject(), replyTo: new Types.ObjectId(), // Set to a non-existing ObjectId }; diff --git a/tests/resolvers/DirectChatMessage/sender.spec.ts b/tests/resolvers/ChatMessage/sender.spec.ts similarity index 78% rename from tests/resolvers/DirectChatMessage/sender.spec.ts rename to tests/resolvers/ChatMessage/sender.spec.ts index 399de17579..0f66293867 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); @@ -42,7 +42,7 @@ describe("resolvers -> DirectChatMessage -> sender", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); const parent = { - ...testDirectChatMessage?.toObject(), + ...testChatMessage?.toObject(), sender: new Types.ObjectId(), // Set to a non-existing ObjectId }; diff --git a/tests/resolvers/DirectChat/organization.spec.ts b/tests/resolvers/DirectChat/organization.spec.ts deleted file mode 100644 index 70d8c99476..0000000000 --- a/tests/resolvers/DirectChat/organization.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import "dotenv/config"; -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"; - -let testDirectChat: TestDirectChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChat(); - testDirectChat = userOrgChat[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> DirectChat -> organization", () => { - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - - const organizationPayload = await organizationResolver?.(parent, {}, {}); - - const organization = await Organization.findOne({ - _id: testDirectChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - }); - - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - - const organizationPayload = await organizationResolver?.(parent, {}, {}); - - const organization = await Organization.findOne({ - _id: testDirectChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - }); -}); 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/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createChat.spec.ts similarity index 74% rename from tests/resolvers/Mutation/createDirectChat.spec.ts rename to tests/resolvers/Mutation/createChat.spec.ts index 7c46e94092..049dfc459a 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 { @@ -38,7 +38,7 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> createDirectChat", () => { +describe("resolvers -> Mutation -> createChat", () => { afterEach(() => { vi.doUnmock("../../../src/constants"); vi.resetModules(); @@ -50,20 +50,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 +79,11 @@ describe("resolvers -> Mutation -> createDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { organizationId: testOrganization?.id, userIds: [new Types.ObjectId().toString()], + isGroup: true }, }; @@ -89,37 +91,38 @@ 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: true }, }; 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?.( + 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/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts new file mode 100644 index 0000000000..a3e1bbf37d --- /dev/null +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -0,0 +1,100 @@ +import "dotenv/config"; +import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; +import type { TestUserType } from "../../helpers/userAndOrg"; +import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToDirectChat"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testChatMessage: TestChatMessageType; +let testCurrentUser: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const resultArray = await createTestChatMessage(); + testCurrentUser = resultArray[0]; + testChatMessage = resultArray[3]; +}); +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("src -> resolvers -> Subscription -> messageSentToChat", () => { + it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { + const { messageSentToChat: messageSentToChatPayload } = + await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); + + const _args = {}; + const _parent = {}; + const context = { + pubsub: { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { + return _action; + }, + }, + context: { currentUserId: testCurrentUser?._id }, + }; + const variables = { + userId: testCurrentUser?._id, + }; + const payload = { + messageSentToDirectChat: { + sender: testChatMessage?.sender, + }, + }; + // @ts-expect-error-ignore + messageSentToChatPayload.payload = payload; + // @ts-expect-error-ignore + const x = messageSentToChatPayload?.subscribe( + _parent, + _args, + context, + ); + expect(x).not.toBe(null); + expect(await filterFunction(payload, variables)).toBe(true); + + // If current User is sender + expect(await filterFunction(payload, variables)).toBe(true); + }); + + it("user is not notified if it is not a part of DirectChat", async () => { + const { messageSentToChat: messageSentToChatPayload } = + await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); + + const _args = {}; + const _parent = {}; + const context = { + pubsub: { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { + return _action; + }, + }, + context: { currentUserId: testCurrentUser?._id }, + }; + const variables = { + userId: testCurrentUser?._id, + }; + + const payload = { + messageSentToChat: { + sender: "Sender", + }, + }; + // @ts-expect-error-ignore + messageSentToChatPayload.payload = payload; + // @ts-expect-error-ignore + const x = messageSentToChatPayload?.subscribe( + _parent, + _args, + context, + ); + expect(x).not.toBe(null); + expect(await filterFunction(payload, variables)).toBe(false); + }); +}); From 98d06a7530d2cb83938f9f977ced11d590e6d52d Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 00:05:46 +0530 Subject: [PATCH 26/50] fix format --- tests/helpers/chat.ts | 28 +++++++------------ .../ChatMessage/chatMessageBelongsTo.ts | 11 ++++---- tests/resolvers/Mutation/createChat.spec.ts | 12 +++----- .../Subscription/messageSentToChat.spec.ts | 26 ++++++----------- 4 files changed, 28 insertions(+), 49 deletions(-) diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index caee724332..2df17b8170 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -1,9 +1,11 @@ import { nanoid } from "nanoid"; -import type { - InterfaceChat, - InterfaceChatMessage, +import type { InterfaceChat, InterfaceChatMessage } from "../../src/models"; +import { + Chat, + ChatMessage, + DirectChat, + DirectChatMessage, } from "../../src/models"; -import { Chat, ChatMessage, DirectChat, DirectChatMessage } from "../../src/models"; import type { TestOrganizationType, TestUserType } from "./userAndOrg"; import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; @@ -13,8 +15,7 @@ export type TestChatType = | null; export type TestChatMessageType = - | (InterfaceChatMessage & - Document) + | (InterfaceChatMessage & Document) | null; export const createTestChat = async (): Promise< @@ -35,20 +36,11 @@ export const createTestChat = async (): Promise< }; export const createTestChatMessage = async (): Promise< - [ - TestUserType, - TestOrganizationType, - TestChatType, - TestChatMessageType, - ] + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] > => { - const [testUser, testOrganization, testChat] = - await createTestChat(); + const [testUser, testOrganization, testChat] = await createTestChat(); - const chatMessage = await createChatMessage( - testUser?._id, - testChat?._id, - ); + const chatMessage = await createChatMessage(testUser?._id, testChat?._id); if (testChat && testUser) { const testChatMessage = await ChatMessage.create({ diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts index fb0140edf7..8b13a3c641 100644 --- a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts @@ -34,16 +34,17 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { throw new Error("directChatMessageBelongsToResolver is not a function."); } - const chatMessageBelongsToPayload = - await chatMessageBelongsToResolver(parent, {}, {}); + const chatMessageBelongsToPayload = await chatMessageBelongsToResolver( + parent, + {}, + {}, + ); const chatMessageBelongsTo = await Chat.findOne({ _id: testChatMessage?.chatMessageBelongsTo, }).lean(); - expect(chatMessageBelongsToPayload).toEqual( - chatMessageBelongsTo, - ); + expect(chatMessageBelongsToPayload).toEqual(chatMessageBelongsTo); }); it(`throws NotFoundError if no directChat exists`, async () => { const { requestContext } = await import("../../../src/libraries"); diff --git a/tests/resolvers/Mutation/createChat.spec.ts b/tests/resolvers/Mutation/createChat.spec.ts index 049dfc459a..d9a900f6dd 100644 --- a/tests/resolvers/Mutation/createChat.spec.ts +++ b/tests/resolvers/Mutation/createChat.spec.ts @@ -54,7 +54,7 @@ describe("resolvers -> Mutation -> createChat", () => { data: { organizationId: new Types.ObjectId().toString(), userIds: [], - isGroup: true + isGroup: true, }, }; const context = { @@ -83,7 +83,7 @@ describe("resolvers -> Mutation -> createChat", () => { data: { organizationId: testOrganization?.id, userIds: [new Types.ObjectId().toString()], - isGroup: true + isGroup: true, }, }; @@ -105,7 +105,7 @@ describe("resolvers -> Mutation -> createChat", () => { data: { organizationId: testOrganization?.id, userIds: [testUser?.id], - isGroup: true + isGroup: true, }, }; @@ -116,11 +116,7 @@ describe("resolvers -> Mutation -> createChat", () => { "../../../src/resolvers/Mutation/createChat" ); - const createChatPayload = await createChatResolver?.( - {}, - args, - context, - ); + const createChatPayload = await createChatResolver?.({}, args, context); expect(createChatPayload).toEqual( expect.objectContaining({ diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts index a3e1bbf37d..ea5f78218d 100644 --- a/tests/resolvers/Subscription/messageSentToChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -23,10 +23,9 @@ afterAll(async () => { describe("src -> resolvers -> Subscription -> messageSentToChat", () => { it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { - const { messageSentToChat: messageSentToChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToChat" - ); + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); const _args = {}; const _parent = {}; @@ -49,11 +48,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { // @ts-expect-error-ignore messageSentToChatPayload.payload = payload; // @ts-expect-error-ignore - const x = messageSentToChatPayload?.subscribe( - _parent, - _args, - context, - ); + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); expect(await filterFunction(payload, variables)).toBe(true); @@ -62,10 +57,9 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { }); it("user is not notified if it is not a part of DirectChat", async () => { - const { messageSentToChat: messageSentToChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToChat" - ); + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); const _args = {}; const _parent = {}; @@ -89,11 +83,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { // @ts-expect-error-ignore messageSentToChatPayload.payload = payload; // @ts-expect-error-ignore - const x = messageSentToChatPayload?.subscribe( - _parent, - _args, - context, - ); + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); expect(await filterFunction(payload, variables)).toBe(false); }); From 5a61b43ec00d1713fcf0910ee0c3d6d5522508db Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 00:42:16 +0530 Subject: [PATCH 27/50] fix test cases --- tests/helpers/chat.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 2df17b8170..bae8bc203e 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -27,6 +27,9 @@ export const createTestChat = async (): Promise< creatorId: testUser._id, users: [testUser._id], organization: testOrganization._id, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), }); return [testUser, testOrganization, testChat]; @@ -48,6 +51,8 @@ export const createTestChatMessage = async (): Promise< sender: testUser._id, replyTo: chatMessage?._id, messageContent: `msgContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), }); return [testUser, testOrganization, testChat, testChatMessage]; } else { @@ -69,6 +74,8 @@ export const createTestMessageForMultipleUser = async ( chatMessageBelongsTo: testChat._id, sender: senderId, messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), }); return testChat; @@ -83,6 +90,9 @@ export const createTestChatwithUsers = async ( creatorId: creator, users: users, organization: organizationId, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), }); return testChat; }; @@ -95,6 +105,8 @@ export const createChatMessage = async ( chatMessageBelongsTo: directChatId, sender: senderId, messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), }); return chatMessage; From a84f1c6d8325cd396567af5e69027b659c3816f7 Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 01:11:20 +0530 Subject: [PATCH 28/50] fix tests --- tests/helpers/chat.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index bae8bc203e..26e7335ba7 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -53,6 +53,7 @@ export const createTestChatMessage = async (): Promise< messageContent: `msgContent${nanoid().toLowerCase()}`, createdAt: new Date(), updatedAt: new Date(), + type: "STRING", }); return [testUser, testOrganization, testChat, testChatMessage]; } else { @@ -76,6 +77,7 @@ export const createTestMessageForMultipleUser = async ( messageContent: `messageContent${nanoid().toLowerCase()}`, createdAt: new Date(), updatedAt: new Date(), + type: "STRING", }); return testChat; @@ -104,6 +106,7 @@ export const createChatMessage = async ( const chatMessage = await ChatMessage.create({ chatMessageBelongsTo: directChatId, sender: senderId, + type: "STRING", messageContent: `messageContent${nanoid().toLowerCase()}`, createdAt: new Date(), updatedAt: new Date(), From 4d65b0369d722024f7a8835ce7ed1b249a2327cb Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 01:38:41 +0530 Subject: [PATCH 29/50] fix tests --- tests/helpers/chat.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 26e7335ba7..78c81e2647 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -47,7 +47,7 @@ export const createTestChatMessage = async (): Promise< if (testChat && testUser) { const testChatMessage = await ChatMessage.create({ - directChatMessageBelongsTo: testChat._id, + chatMessageBelongsTo: testChat._id, sender: testUser._id, replyTo: chatMessage?._id, messageContent: `msgContent${nanoid().toLowerCase()}`, @@ -101,10 +101,10 @@ export const createTestChatwithUsers = async ( export const createChatMessage = async ( senderId: string, - directChatId: string, + chatId: string, ): Promise => { const chatMessage = await ChatMessage.create({ - chatMessageBelongsTo: directChatId, + chatMessageBelongsTo: chatId, sender: senderId, type: "STRING", messageContent: `messageContent${nanoid().toLowerCase()}`, From c23008b2c894b2817489b76e19de901063e50f8c Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 09:49:35 +0530 Subject: [PATCH 30/50] fix: test cases --- tests/resolvers/Subscription/messageSentToChat.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts index ea5f78218d..556b68ffbb 100644 --- a/tests/resolvers/Subscription/messageSentToChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -5,7 +5,7 @@ import type mongoose from "mongoose"; 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"; let MONGOOSE_INSTANCE: typeof mongoose; let testChatMessage: TestChatMessageType; @@ -41,7 +41,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { userId: testCurrentUser?._id, }; const payload = { - messageSentToDirectChat: { + messageSentToChat: { sender: testChatMessage?.sender, }, }; From a539e3eb87f685cb521fb1be63e4c932c0f91beb Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 9 Aug 2024 11:57:40 +0530 Subject: [PATCH 31/50] fix: test cases --- tests/resolvers/Subscription/messageSentToChat.spec.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts index 556b68ffbb..14daf9413f 100644 --- a/tests/resolvers/Subscription/messageSentToChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -6,6 +6,7 @@ import type { TestChatMessageType } from "../../helpers/chat"; import { createTestChatMessage } from "../../helpers/chat"; import type { TestUserType } from "../../helpers/userAndOrg"; import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToChat"; +import { chatMessageBelongsTo } from "../../../src/resolvers/ChatMessage/chatMessageBelongsTo"; let MONGOOSE_INSTANCE: typeof mongoose; let testChatMessage: TestChatMessageType; @@ -42,7 +43,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { }; const payload = { messageSentToChat: { - sender: testChatMessage?.sender, + chatMessageBelongsTo: testChatMessage?.chatMessageBelongsTo, }, }; // @ts-expect-error-ignore @@ -51,9 +52,6 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { const x = messageSentToChatPayload?.subscribe(_parent, _args, context); expect(x).not.toBe(null); expect(await filterFunction(payload, variables)).toBe(true); - - // If current User is sender - expect(await filterFunction(payload, variables)).toBe(true); }); it("user is not notified if it is not a part of DirectChat", async () => { From 074b79c9de7a7156a3084a6643df6739fdec2da0 Mon Sep 17 00:00:00 2001 From: Disha Date: Sat, 10 Aug 2024 23:55:53 +0530 Subject: [PATCH 32/50] fix: test cases --- docker-compose.dev.yaml | 2 +- src/types/generatedGraphQLTypes.ts | 4 +- tests/helpers/chat.ts | 23 ++ tests/resolvers/Chat/admins.spec.ts | 0 tests/resolvers/Chat/organization.spec.ts | 0 ...ongsTo.ts => chatMessageBelongsTo.spec.ts} | 6 +- .../{replyTo.ts => replyTo.spec.ts} | 38 ++- .../Mutation/removeGroupChat.spec.ts | 243 ------------------ .../Mutation/sendMessageToChat.spec.ts | 185 +++++++++++++ 9 files changed, 247 insertions(+), 254 deletions(-) delete mode 100644 tests/resolvers/Chat/admins.spec.ts delete mode 100644 tests/resolvers/Chat/organization.spec.ts rename tests/resolvers/ChatMessage/{chatMessageBelongsTo.ts => chatMessageBelongsTo.spec.ts} (90%) rename tests/resolvers/ChatMessage/{replyTo.ts => replyTo.spec.ts} (65%) delete mode 100644 tests/resolvers/Mutation/removeGroupChat.spec.ts create mode 100644 tests/resolvers/Mutation/sendMessageToChat.spec.ts diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 2c0599b401..0477179afb 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -28,7 +28,7 @@ services: - mongodb - redis-stack-server environment: - - mongodb+srv://disha:disha@test.hz7knd5.mongodb.net/?retryWrites=true&w=majority&appName=test + - mongodb+srv://disha:disha@cluster0.ynjfu.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0 - REDIS_HOST=redis-stack-server - REDIS_PORT=6379 diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index f281e86b54..c1ece328aa 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -3296,7 +3296,7 @@ export type DirectiveResolverFn TResult | Promise; /** Mapping of union types */ -export type ResolversUnionTypes> = { +export type ResolversUnionTypes<_RefType extends Record> = { ConnectionError: ( InvalidCursor ) | ( MaximumValueError ); CreateAdminError: ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); CreateCommentError: ( PostNotFoundError ); @@ -3305,7 +3305,7 @@ export type ResolversUnionTypes> = { }; /** Mapping of interface types */ -export type ResolversInterfaceTypes> = { +export type ResolversInterfaceTypes<_RefType extends Record> = { ConnectionPageInfo: ( DefaultConnectionPageInfo ); Error: ( MemberNotFoundError ) | ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( PostNotFoundError ) | ( UnauthenticatedError ) | ( UnauthorizedError ) | ( UserNotAuthorizedAdminError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); FieldError: ( InvalidCursor ) | ( MaximumLengthError ) | ( MaximumValueError ) | ( MinimumLengthError ) | ( MinimumValueError ); diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 78c81e2647..72ad07ff1b 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -61,6 +61,29 @@ export const createTestChatMessage = async (): Promise< } }; +export const createTestChatMessageWithoutReply = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] +> => { + const [testUser, testOrganization, testChat] = await createTestChat(); + + const chatMessage = await createChatMessage(testUser?._id, testChat?._id); + + 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, diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/resolvers/Chat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts similarity index 90% rename from tests/resolvers/ChatMessage/chatMessageBelongsTo.ts rename to tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts index 8b13a3c641..c7c0b97407 100644 --- a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts @@ -31,7 +31,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { } if (typeof chatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); + throw new Error("chatMessageBelongsToResolver is not a function."); } const chatMessageBelongsToPayload = await chatMessageBelongsToResolver( @@ -54,7 +54,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { const parent = { ...testChatMessage?.toObject(), - directChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId + chatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId }; if (!parent) { @@ -62,7 +62,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { } if (typeof chatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); + throw new Error("chatMessageBelongsToResolver is not a function."); } try { diff --git a/tests/resolvers/ChatMessage/replyTo.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts similarity index 65% rename from tests/resolvers/ChatMessage/replyTo.ts rename to tests/resolvers/ChatMessage/replyTo.spec.ts index b720cfe97c..18143d8a66 100644 --- a/tests/resolvers/ChatMessage/replyTo.ts +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -5,25 +5,31 @@ 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 { createTestChatMessage } 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 () => { MONGOOSE_INSTANCE = await connect(); - const temp = await createTestChatMessage(); - testChatMessage = temp[3]; + const temp = await createTestChatMessageWithoutReply(); + const temp1 = await createTestChatMessage(); + testChatMessageWithoutReply = temp[3]; + testChatMessage = temp1[3]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { - it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { +describe("resolvers -> DirectChatMessage -> replyTo", () => { + it(`returns directChat object for parent.replyTo`, async () => { const parent = testChatMessage?.toObject(); if (!parent) { @@ -69,4 +75,26 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { expect((error as Error).message).toEqual(MESSAGE_NOT_FOUND_ERROR.MESSAGE); } }); + it(`return null if no replyTo`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => message); + + 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/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/sendMessageToChat.spec.ts b/tests/resolvers/Mutation/sendMessageToChat.spec.ts new file mode 100644 index 0000000000..5361e8a2a0 --- /dev/null +++ b/tests/resolvers/Mutation/sendMessageToChat.spec.ts @@ -0,0 +1,185 @@ +import "dotenv/config"; +import type { Document } from "mongoose"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +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 { sendMessageToChat as sendMessageToChatResolver } from "../../../src/resolvers/Mutation/sendMessageToChat"; +import { + CHAT_NOT_FOUND_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import { + beforeAll, + afterAll, + afterEach, + describe, + it, + expect, + vi, +} from "vitest"; +import { createTestUserFunc } from "../../helpers/user"; +import type { TestUserType } from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testUsers: TestUserType[]; +let testChat: InterfaceChat & Document; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const tempUser1 = await createTestUserFunc(); + const tempUser2 = await createTestUserFunc(); + testUsers = [tempUser1, tempUser2]; + + const testOrganization = await Organization.create({ + name: "name", + description: "description", + isPublic: true, + creatorId: testUsers[0]?._id, + admins: [testUsers[0]?._id], + members: [testUsers[0]?._id], + visibleInSearch: true, + }); + + await User.updateOne( + { + _id: testUsers[0]?._id, + }, + { + $set: { + createdOrganizations: [testOrganization._id], + adminFor: [testOrganization._id], + joinedOrganizations: [testOrganization._id], + }, + }, + ); + + 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", + }); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { + afterEach(async () => { + vi.doUnmock("../../../src/constants"); + vi.resetModules(); + }); + + it(`throws NotFoundError if no directChat exists with _id === args.chatId`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => message); + try { + const args: MutationSendMessageToChatArgs = { + chatId: new Types.ObjectId().toString(), + messageContent: "", + type: "STRING", + }; + + const context = { userId: testUsers[0]?.id }; + + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); + + 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); + } + }); + + 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: MutationSendMessageToChatArgs = { + chatId: testChat.id, + messageContent: "", + type: "STRING", + }; + + const context = { + userId: new Types.ObjectId().toString(), + }; + + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); + + 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); + } + }); + + it(`creates the directChatMessage and returns it`, async () => { + await Chat.updateOne( + { + _id: testChat._id, + }, + { + $push: { + users: testUsers[0]?._id, + }, + }, + ); + + const args: MutationSendMessageToChatArgs = { + chatId: testChat.id, + messageContent: "messageContent", + type: "STRING", + }; + + const pubsub = { + publish: ( + _action: "MESSAGE_SENT_TO_CHAT", + _payload: { + messageSentToChat: InterfaceChatMessage; + }, + ): { + _action: string; + _payload: { messageSentToChat: InterfaceChatMessage }; + } => { + return { _action, _payload }; + }, + }; + + const context = { + userId: testUsers[0]?.id, + pubsub, + }; + + const sendMessageToChatPayload = await sendMessageToChatResolver?.( + {}, + args, + context, + ); + + expect(sendMessageToChatPayload).toEqual( + expect.objectContaining({ + chatMessageBelongsTo: testChat._id, + sender: testUsers[0]?._id, + messageContent: "messageContent", + type: "STRING", + }), + ); + }); +}); From 15867324c432974fbe4b317dd836cec189a5fb8e Mon Sep 17 00:00:00 2001 From: Disha Date: Thu, 15 Aug 2024 12:03:47 +0530 Subject: [PATCH 33/50] added test cases --- docker-compose.dev.yaml | 2 +- src/types/generatedGraphQLTypes.ts | 4 +- tests/resolvers/Chat/admins.spec.ts | 0 tests/resolvers/Chat/organization.spec.ts | 0 ...ongsTo.ts => chatMessageBelongsTo.spec.ts} | 2 +- .../{replyTo.ts => replyTo.spec.ts} | 2 +- .../Mutation/removeGroupChat.spec.ts | 243 ------------------ 7 files changed, 5 insertions(+), 248 deletions(-) delete mode 100644 tests/resolvers/Chat/admins.spec.ts delete mode 100644 tests/resolvers/Chat/organization.spec.ts rename tests/resolvers/ChatMessage/{chatMessageBelongsTo.ts => chatMessageBelongsTo.spec.ts} (97%) rename tests/resolvers/ChatMessage/{replyTo.ts => replyTo.spec.ts} (97%) delete mode 100644 tests/resolvers/Mutation/removeGroupChat.spec.ts diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 2c0599b401..056cb62125 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -28,7 +28,7 @@ services: - mongodb - redis-stack-server environment: - - mongodb+srv://disha:disha@test.hz7knd5.mongodb.net/?retryWrites=true&w=majority&appName=test + - mongodb://localhost:27017/talawa-api - REDIS_HOST=redis-stack-server - REDIS_PORT=6379 diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index f281e86b54..c1ece328aa 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -3296,7 +3296,7 @@ export type DirectiveResolverFn TResult | Promise; /** Mapping of union types */ -export type ResolversUnionTypes> = { +export type ResolversUnionTypes<_RefType extends Record> = { ConnectionError: ( InvalidCursor ) | ( MaximumValueError ); CreateAdminError: ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); CreateCommentError: ( PostNotFoundError ); @@ -3305,7 +3305,7 @@ export type ResolversUnionTypes> = { }; /** Mapping of interface types */ -export type ResolversInterfaceTypes> = { +export type ResolversInterfaceTypes<_RefType extends Record> = { ConnectionPageInfo: ( DefaultConnectionPageInfo ); Error: ( MemberNotFoundError ) | ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( PostNotFoundError ) | ( UnauthenticatedError ) | ( UnauthorizedError ) | ( UserNotAuthorizedAdminError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); FieldError: ( InvalidCursor ) | ( MaximumLengthError ) | ( MaximumValueError ) | ( MinimumLengthError ) | ( MinimumValueError ); diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/resolvers/Chat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts similarity index 97% rename from tests/resolvers/ChatMessage/chatMessageBelongsTo.ts rename to tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts index 8b13a3c641..8788aac385 100644 --- a/tests/resolvers/ChatMessage/chatMessageBelongsTo.ts +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts @@ -50,7 +50,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { const { requestContext } = await import("../../../src/libraries"); const spy = vi .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); + .mockImplementationOnce((message: any) => message); const parent = { ...testChatMessage?.toObject(), diff --git a/tests/resolvers/ChatMessage/replyTo.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts similarity index 97% rename from tests/resolvers/ChatMessage/replyTo.ts rename to tests/resolvers/ChatMessage/replyTo.spec.ts index b720cfe97c..ca08650c1f 100644 --- a/tests/resolvers/ChatMessage/replyTo.ts +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -46,7 +46,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { const { requestContext } = await import("../../../src/libraries"); const spy = vi .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); + .mockImplementationOnce((message: any) => message); const parent = { ...testChatMessage?.toObject(), 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([]); - }); -}); From 15d6beddc9637fca3cf89ce90b58fa11de3085a5 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 18 Aug 2024 19:11:57 +0530 Subject: [PATCH 34/50] removed unwanted code --- codegen.ts | 10 -- docker-compose.dev.yaml | 4 - src/models/DirectChat.ts | 75 ----------- src/models/DirectChatMessage.ts | 84 ------------ src/models/GroupChat.ts | 97 ------------- src/models/GroupChatMessage.ts | 81 ----------- src/models/index.ts | 4 - src/resolvers/DirectChat/creator.ts | 12 -- src/resolvers/DirectChat/index.ts | 24 ---- src/resolvers/DirectChat/messages.ts | 14 -- src/resolvers/DirectChat/organization.ts | 28 ---- src/resolvers/DirectChat/users.ts | 14 -- .../directChatMessageBelongsTo.ts | 33 ----- src/resolvers/DirectChatMessage/index.ts | 12 -- src/resolvers/DirectChatMessage/receiver.ts | 34 ----- src/resolvers/DirectChatMessage/replyTo.ts | 30 ----- src/resolvers/DirectChatMessage/sender.ts | 32 ----- src/resolvers/GroupChat/creator.ts | 20 --- src/resolvers/GroupChat/index.ts | 12 -- src/resolvers/GroupChat/messages.ts | 22 --- src/resolvers/GroupChat/organization.ts | 36 ----- src/resolvers/GroupChat/users.ts | 22 --- .../groupChatMessageBelongsTo.ts | 33 ----- src/resolvers/GroupChatMessage/index.ts | 10 -- src/resolvers/GroupChatMessage/replyTo.ts | 29 ---- src/resolvers/GroupChatMessage/sender.ts | 32 ----- src/resolvers/Mutation/addUserToGroupChat.ts | 127 ------------------ src/resolvers/Mutation/createGroupChat.ts | 93 ------------- src/resolvers/Mutation/index.ts | 12 -- src/resolvers/Mutation/removeDirectChat.ts | 81 ----------- src/resolvers/Mutation/removeGroupChat.ts | 80 ----------- .../Mutation/sendMessageToDirectChat.ts | 72 ---------- .../Mutation/sendMessageToGroupChat.ts | 88 ------------ src/resolvers/Query/directChatById.ts | 31 ----- src/resolvers/Query/directChatsByUserID.ts | 28 ---- .../Query/directChatsMessagesByChatID.ts | 31 ----- src/resolvers/Query/groupChatById.ts | 31 ----- src/resolvers/Query/groupChatsByUserId.ts | 30 ----- src/resolvers/Query/index.ts | 10 -- src/resolvers/index.ts | 8 -- src/types/generatedGraphQLTypes.ts | 20 ++- tests/helpers/chat.ts | 11 +- tests/helpers/directChat.ts | 115 ---------------- tests/helpers/groupChat.ts | 81 ----------- tests/resolvers/Chat/admins.spec.ts | 40 ++++++ tests/resolvers/Chat/organization.spec.ts | 51 +++++++ tests/resolvers/Chat/users.spec.ts | 2 +- tests/resolvers/GroupChat/creator.spec.ts | 40 ------ tests/resolvers/GroupChat/messages.spec.ts | 39 ------ .../resolvers/GroupChat/organization.spec.ts | 46 ------- tests/resolvers/GroupChat/users.spec.ts | 39 ------ 51 files changed, 103 insertions(+), 1907 deletions(-) delete mode 100644 src/models/DirectChat.ts delete mode 100644 src/models/DirectChatMessage.ts delete mode 100644 src/models/GroupChat.ts delete mode 100644 src/models/GroupChatMessage.ts delete mode 100644 src/resolvers/DirectChat/creator.ts delete mode 100644 src/resolvers/DirectChat/index.ts delete mode 100644 src/resolvers/DirectChat/messages.ts delete mode 100644 src/resolvers/DirectChat/organization.ts delete mode 100644 src/resolvers/DirectChat/users.ts delete mode 100644 src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts delete mode 100644 src/resolvers/DirectChatMessage/index.ts delete mode 100644 src/resolvers/DirectChatMessage/receiver.ts delete mode 100644 src/resolvers/DirectChatMessage/replyTo.ts delete mode 100644 src/resolvers/DirectChatMessage/sender.ts delete mode 100644 src/resolvers/GroupChat/creator.ts delete mode 100644 src/resolvers/GroupChat/index.ts delete mode 100644 src/resolvers/GroupChat/messages.ts delete mode 100644 src/resolvers/GroupChat/organization.ts delete mode 100644 src/resolvers/GroupChat/users.ts delete mode 100644 src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts delete mode 100644 src/resolvers/GroupChatMessage/index.ts delete mode 100644 src/resolvers/GroupChatMessage/replyTo.ts delete mode 100644 src/resolvers/GroupChatMessage/sender.ts delete mode 100644 src/resolvers/Mutation/addUserToGroupChat.ts delete mode 100644 src/resolvers/Mutation/createGroupChat.ts delete mode 100644 src/resolvers/Mutation/removeDirectChat.ts delete mode 100644 src/resolvers/Mutation/removeGroupChat.ts delete mode 100644 src/resolvers/Mutation/sendMessageToDirectChat.ts delete mode 100644 src/resolvers/Mutation/sendMessageToGroupChat.ts delete mode 100644 src/resolvers/Query/directChatById.ts delete mode 100644 src/resolvers/Query/directChatsByUserID.ts delete mode 100644 src/resolvers/Query/directChatsMessagesByChatID.ts delete mode 100644 src/resolvers/Query/groupChatById.ts delete mode 100644 src/resolvers/Query/groupChatsByUserId.ts delete mode 100644 tests/helpers/directChat.ts delete mode 100644 tests/helpers/groupChat.ts create mode 100644 tests/resolvers/Chat/admins.spec.ts create mode 100644 tests/resolvers/Chat/organization.spec.ts delete mode 100644 tests/resolvers/GroupChat/creator.spec.ts delete mode 100644 tests/resolvers/GroupChat/messages.spec.ts delete mode 100644 tests/resolvers/GroupChat/organization.spec.ts delete mode 100644 tests/resolvers/GroupChat/users.spec.ts diff --git a/codegen.ts b/codegen.ts index 40d5c18d05..1a2ab9b479 100644 --- a/codegen.ts +++ b/codegen.ts @@ -46,15 +46,10 @@ const config: CodegenConfig = { Community: "../models/Community#InterfaceCommunity", - DirectChat: "../models/DirectChat#InterfaceDirectChat", - Chat: "../models/Chat#InterfaceChat", ChatMessage: "../models/ChatMessage#InterfaceChatMessage", - DirectChatMessage: - "../models/DirectChatMessage#InterfaceDirectChatMessage", - Donation: "../models/Donation#InterfaceDonation", Event: "../models/Event#InterfaceEvent", @@ -79,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/docker-compose.dev.yaml b/docker-compose.dev.yaml index 7468e64c3e..056cb62125 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -28,11 +28,7 @@ services: - mongodb - redis-stack-server environment: -<<<<<<< HEAD - mongodb://localhost:27017/talawa-api -======= - - mongodb+srv://disha:disha@cluster0.ynjfu.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0 ->>>>>>> 9926e63d4c242fc939f8e981d1086f31d5c121ee - REDIS_HOST=redis-stack-server - REDIS_PORT=6379 diff --git a/src/models/DirectChat.ts b/src/models/DirectChat.ts deleted file mode 100644 index 3715e0f687..0000000000 --- a/src/models/DirectChat.ts +++ /dev/null @@ -1,75 +0,0 @@ -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"; -/** - * Interface representing a document for direct chat in MongoDB. - */ -export interface InterfaceDirectChat { - _id: Types.ObjectId; - users: PopulatedDoc[]; - messages: PopulatedDoc[]; - creatorId: PopulatedDoc; - organization: PopulatedDoc; - status: string; - createdAt: Date; - updatedAt: Date; -} - -/** - * Mongoose schema for a direct 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 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. - */ -const directChatSchema = new Schema( - { - users: [ - { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - ], - messages: [ - { - type: Schema.Types.ObjectId, - ref: "DirectChatMessage", - }, - ], - creatorId: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], - default: "ACTIVE", - }, - }, - { - timestamps: true, - }, -); - -// Add logging middleware for directChatSchema -createLoggingMiddleware(directChatSchema, "DirectChat"); - -/** - * Retrieves or creates the Mongoose model for DirectChat. - * Prevents Mongoose OverwriteModelError during testing. - */ -const directChatModel = (): Model => - model("DirectChat", directChatSchema); - -// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. -export const DirectChat = (models.DirectChat || - directChatModel()) as ReturnType; diff --git a/src/models/DirectChatMessage.ts b/src/models/DirectChatMessage.ts deleted file mode 100644 index 5d159f9a25..0000000000 --- a/src/models/DirectChatMessage.ts +++ /dev/null @@ -1,84 +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; - replyTo: 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, - }, - replyTo: { - type: Schema.Types.ObjectId, - ref: "DirectChatMessage", - required: false, - }, - 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 579cb4d98c..0000000000 --- a/src/models/GroupChatMessage.ts +++ /dev/null @@ -1,81 +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; - replyTo: PopulatedDoc; - 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, - }, - replyTo: { - type: Schema.Types.ObjectId, - ref: "GroupChatMessage", - required: false, - }, - 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 bd89ca35f3..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"; diff --git a/src/resolvers/DirectChat/creator.ts b/src/resolvers/DirectChat/creator.ts deleted file mode 100644 index 02fed5c4a9..0000000000 --- a/src/resolvers/DirectChat/creator.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -/** - * This resolver function will fetch and return the specified Direct 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) => { - return await User.findOne({ - _id: parent.creatorId, - }).lean(); -}; 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/DirectChat/organization.ts b/src/resolvers/DirectChat/organization.ts deleted file mode 100644 index 9073af15f4..0000000000 --- a/src/resolvers/DirectChat/organization.ts +++ /dev/null @@ -1,28 +0,0 @@ -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"; -/** - * This resolver function will fetch and return the Organization for the 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 Organization data. - */ -export const organization: DirectChatResolvers["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) cacheOrganizations([organization]); - - return organization as InterfaceOrganization; -}; diff --git a/src/resolvers/DirectChat/users.ts b/src/resolvers/DirectChat/users.ts deleted file mode 100644 index ebb3893c7f..0000000000 --- a/src/resolvers/DirectChat/users.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -/** - * This resolver function will fetch and return the list of all direct 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) => { - return await User.find({ - _id: { - $in: parent.users, - }, - }).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 41c8ee48a1..0000000000 --- a/src/resolvers/DirectChatMessage/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { directChatMessageBelongsTo } from "./directChatMessageBelongsTo"; -import { receiver } from "./receiver"; -import { replyTo } from "./replyTo"; -import { sender } from "./sender"; - -export const DirectChatMessage: DirectChatMessageResolvers = { - directChatMessageBelongsTo, - receiver, - sender, - replyTo, -}; 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/replyTo.ts b/src/resolvers/DirectChatMessage/replyTo.ts deleted file mode 100644 index bcc6ee9f1a..0000000000 --- a/src/resolvers/DirectChatMessage/replyTo.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { DirectChatMessage } from "../../models"; -import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; -/** - * This resolver function will fetch and return the receiver(user) of the Direct 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 replyTo: DirectChatMessageResolvers["replyTo"] = async ( - parent, -) => { - if (parent.replyTo) { - const result = await DirectChatMessage.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/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/index.ts b/src/resolvers/GroupChat/index.ts deleted file mode 100644 index 9c81560015..0000000000 --- a/src/resolvers/GroupChat/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { creator } from "./creator"; -import { messages } from "./messages"; -import { organization } from "./organization"; -import { users } from "./users"; - -export const GroupChat: GroupChatResolvers = { - creator, - messages, - organization, - users, -}; 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 9419e428eb..0000000000 --- a/src/resolvers/GroupChatMessage/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { groupChatMessageBelongsTo } from "./groupChatMessageBelongsTo"; -import { replyTo } from "./replyTo"; -import { sender } from "./sender"; - -export const GroupChatMessage: GroupChatMessageResolvers = { - groupChatMessageBelongsTo, - sender, - replyTo, -}; diff --git a/src/resolvers/GroupChatMessage/replyTo.ts b/src/resolvers/GroupChatMessage/replyTo.ts deleted file mode 100644 index 62d74c4297..0000000000 --- a/src/resolvers/GroupChatMessage/replyTo.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChatMessage } from "../../models"; -import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; -/** - * This resolver function will fetch and return the receiver(user) of the Direct 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 replyTo: GroupChatMessageResolvers["replyTo"] = async (parent) => { - console.log("PARENT ", parent); - if (parent.replyTo) { - const result = await GroupChatMessage.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/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/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/index.ts b/src/resolvers/Mutation/index.ts index bef02acf23..1f616cda32 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -7,7 +7,6 @@ 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"; @@ -32,7 +31,6 @@ 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"; @@ -65,7 +63,6 @@ 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"; @@ -73,7 +70,6 @@ import { removeFund } from "./removeFund"; import { removeEventVolunteerGroup } from "./removeEventVolunteerGroup"; import { removeFundraisingCampaign } from "./removeFundraisingCampaign"; import { removeFundraisingCampaignPledge } from "./removeFundraisingCampaingPledge"; -import { removeGroupChat } from "./removeGroupChat"; import { removeMember } from "./removeMember"; import { removeOrganization } from "./removeOrganization"; import { removeOrganizationCustomField } from "./removeOrganizationCustomField"; @@ -90,9 +86,7 @@ import { resetCommunity } from "./resetCommunity"; import { revokeRefreshTokenForUser } from "./revokeRefreshTokenForUser"; import { saveFcmToken } from "./saveFcmToken"; import { sendMembershipRequest } from "./sendMembershipRequest"; -import { sendMessageToDirectChat } from "./sendMessageToDirectChat"; import { sendMessageToChat } from "./sendMessageToChat"; -import { sendMessageToGroupChat } from "./sendMessageToGroupChat"; import { signUp } from "./signUp"; import { togglePostPin } from "./togglePostPin"; import { unassignUserTag } from "./unassignUserTag"; @@ -134,7 +128,6 @@ export const Mutation: MutationResolvers = { addOrganizationImage, addUserCustomData, addUserImage, - addUserToGroupChat, adminRemoveGroup, addUserToUserFamily, removeUserFamily, @@ -160,7 +153,6 @@ export const Mutation: MutationResolvers = { createEvent, createFund, createFundraisingCampaign, - createGroupChat, createMessageChat, createOrganization, createNote, @@ -196,13 +188,11 @@ export const Mutation: MutationResolvers = { removeAgendaItem, removeAgendaSection, removeComment, - removeDirectChat, removeEvent, removeEventAttendee, removeEventVolunteer, removeFund, removeEventVolunteerGroup, - removeGroupChat, removeMember, removeOrganization, removeOrganizationCustomField, @@ -217,9 +207,7 @@ export const Mutation: MutationResolvers = { revokeRefreshTokenForUser, saveFcmToken, sendMembershipRequest, - sendMessageToDirectChat, sendMessageToChat, - sendMessageToGroupChat, 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/sendMessageToDirectChat.ts b/src/resolvers/Mutation/sendMessageToDirectChat.ts deleted file mode 100644 index 22d1017e6f..0000000000 --- a/src/resolvers/Mutation/sendMessageToDirectChat.ts +++ /dev/null @@ -1,72 +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, - replyTo: args.replyTo, - }); - - // 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 7592b51c96..0000000000 --- a/src/resolvers/Mutation/sendMessageToGroupChat.ts +++ /dev/null @@ -1,88 +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, - replyTo: args.replyTo, - }); - - // 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/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 6c7a619714..37b55a69d1 100644 --- a/src/resolvers/Query/index.ts +++ b/src/resolvers/Query/index.ts @@ -13,13 +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 { chatById } from "./chatById"; import { chatsByUserId } from "./chatsByUserId"; -import { groupChatById } from "./groupChatById"; -import { groupChatsByUserId } from "./groupChatsByUserId"; import { event } from "./event"; import { eventsByOrganization } from "./eventsByOrganization"; import { eventsByOrganizationConnection } from "./eventsByOrganizationConnection"; @@ -68,11 +63,6 @@ export const Query: QueryResolvers = { customDataByOrganization, chatById, chatsByUserId, - directChatsByUserID, - directChatsMessagesByChatID, - directChatById, - groupChatById, - groupChatsByUserId, event, eventsByOrganization, eventsByOrganizationConnection, diff --git a/src/resolvers/index.ts b/src/resolvers/index.ts index 2267e01ca4..c8db99a68f 100644 --- a/src/resolvers/index.ts +++ b/src/resolvers/index.ts @@ -21,14 +21,10 @@ import { CheckIn } from "./CheckIn"; import { Comment } from "./Comment"; import { Chat } from "./Chat"; import { ChatMessage } from "./ChatMessage"; -import { DirectChat } from "./DirectChat"; -import { DirectChatMessage } from "./DirectChatMessage"; 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"; @@ -56,15 +52,11 @@ const resolvers: Resolvers = { Comment, Chat, ChatMessage, - DirectChat, - DirectChatMessage, Event, EventVolunteer, Feedback, Fund, - GroupChat, UserFamily, - GroupChatMessage, MembershipRequest, Mutation, Organization, diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index c1ece328aa..e67d488dcb 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -10,10 +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 { InterfaceChat as InterfaceChatModel } from '../models/Chat'; import type { InterfaceChatMessage as InterfaceChatMessageModel } from '../models/ChatMessage'; -import type { InterfaceDirectChatMessage as InterfaceDirectChatMessageModel } from '../models/DirectChatMessage'; import type { InterfaceDonation as InterfaceDonationModel } from '../models/Donation'; import type { InterfaceEvent as InterfaceEventModel } from '../models/Event'; import type { InterfaceEventAttendee as InterfaceEventAttendeeModel } from '../models/EventAttendee'; @@ -25,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'; @@ -3367,8 +3363,8 @@ export type ResolversTypes = { DefaultConnectionPageInfo: ResolverTypeWrapper; DeleteAdvertisementPayload: ResolverTypeWrapper & { advertisement?: Maybe }>; DeletePayload: ResolverTypeWrapper; - DirectChat: ResolverTypeWrapper; - DirectChatMessage: ResolverTypeWrapper; + DirectChat: ResolverTypeWrapper & { creator?: Maybe, messages?: Maybe>>, organization?: Maybe, users: Array }>; + DirectChatMessage: ResolverTypeWrapper & { directChatMessageBelongsTo: ResolversTypes['DirectChat'], receiver: ResolversTypes['User'], replyTo?: Maybe, sender: ResolversTypes['User'] }>; Donation: ResolverTypeWrapper; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3404,8 +3400,8 @@ export type ResolversTypes = { FundraisingCampaignPledge: ResolverTypeWrapper; Gender: Gender; Group: ResolverTypeWrapper; - GroupChat: ResolverTypeWrapper; - GroupChatMessage: ResolverTypeWrapper; + GroupChat: ResolverTypeWrapper & { creator?: Maybe, messages?: Maybe>>, organization: ResolversTypes['Organization'], users: Array }>; + GroupChatMessage: ResolverTypeWrapper & { groupChatMessageBelongsTo: ResolversTypes['GroupChat'], replyTo?: Maybe, sender: ResolversTypes['User'] }>; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; InvalidCursor: ResolverTypeWrapper; @@ -3579,8 +3575,8 @@ export type ResolversParentTypes = { DefaultConnectionPageInfo: DefaultConnectionPageInfo; DeleteAdvertisementPayload: Omit & { advertisement?: Maybe }; DeletePayload: DeletePayload; - DirectChat: InterfaceDirectChatModel; - DirectChatMessage: InterfaceDirectChatMessageModel; + DirectChat: Omit & { creator?: Maybe, messages?: Maybe>>, organization?: Maybe, users: Array }; + DirectChatMessage: Omit & { directChatMessageBelongsTo: ResolversParentTypes['DirectChat'], receiver: ResolversParentTypes['User'], replyTo?: Maybe, sender: ResolversParentTypes['User'] }; Donation: InterfaceDonationModel; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3609,8 +3605,8 @@ export type ResolversParentTypes = { FundraisingCampaign: InterfaceFundraisingCampaignModel; FundraisingCampaignPledge: InterfaceFundraisingCampaignPledgesModel; Group: InterfaceGroupModel; - GroupChat: InterfaceGroupChatModel; - GroupChatMessage: InterfaceGroupChatMessageModel; + GroupChat: Omit & { creator?: Maybe, messages?: Maybe>>, organization: ResolversParentTypes['Organization'], users: Array }; + GroupChatMessage: Omit & { groupChatMessageBelongsTo: ResolversParentTypes['GroupChat'], replyTo?: Maybe, sender: ResolversParentTypes['User'] }; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; InvalidCursor: InvalidCursor; diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 72ad07ff1b..71511712ef 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -1,11 +1,6 @@ import { nanoid } from "nanoid"; import type { InterfaceChat, InterfaceChatMessage } from "../../src/models"; -import { - Chat, - ChatMessage, - DirectChat, - DirectChatMessage, -} from "../../src/models"; +import { Chat, ChatMessage } from "../../src/models"; import type { TestOrganizationType, TestUserType } from "./userAndOrg"; import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; @@ -30,6 +25,7 @@ export const createTestChat = async (): Promise< isGroup: true, createdAt: new Date(), updatedAt: new Date(), + admins: [testUser._id], }); return [testUser, testOrganization, testChat]; @@ -42,6 +38,7 @@ export const createTestChatMessage = async (): Promise< [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] > => { const [testUser, testOrganization, testChat] = await createTestChat(); + console.log("TEST CHAT", testChat); const chatMessage = await createChatMessage(testUser?._id, testChat?._id); @@ -66,8 +63,6 @@ export const createTestChatMessageWithoutReply = async (): Promise< > => { const [testUser, testOrganization, testChat] = await createTestChat(); - const chatMessage = await createChatMessage(testUser?._id, testChat?._id); - if (testChat && testUser) { const testChatMessage = await ChatMessage.create({ chatMessageBelongsTo: testChat._id, diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts deleted file mode 100644 index cf4e852500..0000000000 --- a/tests/helpers/directChat.ts +++ /dev/null @@ -1,115 +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(); - - const directChatMessage = await createDirectChatMessage( - testUser?._id, - testUser?._id, - testDirectChat?._id, - ); - - if (testDirectChat && testUser) { - const testDirectChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: testDirectChat._id, - sender: testUser._id, - receiver: testUser._id, - replyTo: directChatMessage?._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 5e9d311f2b..0000000000 --- a/tests/helpers/groupChat.ts +++ /dev/null @@ -1,81 +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(); - - const message = await createGroupChatMessage( - testUser?._id, - testGroupChat?._id, - ); - - if (testGroupChat && testUser) { - const testGroupChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: testGroupChat._id, - sender: testUser._id, - createdAt: new Date(), - messageContent: `messageContent${nanoid().toLowerCase()}`, - replyTo: message?._id, - }); - - return [testUser, testOrganization, testGroupChat, testGroupChatMessage]; - } else { - return [testUser, testOrganization, testGroupChat, null]; - } -}; - -export const createGroupChatMessage = async ( - senderId: string, - groupChatId: string, -): Promise => { - const directChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: groupChatId, - sender: senderId, - createdAt: new Date(), - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return directChatMessage; -}; diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts new file mode 100644 index 0000000000..575fee42b2 --- /dev/null +++ b/tests/resolvers/Chat/admins.spec.ts @@ -0,0 +1,40 @@ +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(); + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Chat -> admins", () => { + it(`returns user object for parent.users`, async () => { + const parent = testChat?.toObject(); + if (!parent) { + throw new Error("Parent object is undefined."); + } + + const usersPayload = await adminsResolver?.(parent, {}, {}); + + const users = await User.find({ + _id: { + $in: testChat?.admins, + }, + }).lean(); + + expect(usersPayload).toEqual(users); + }); +}); diff --git a/tests/resolvers/Chat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts new file mode 100644 index 0000000000..6f413b8f20 --- /dev/null +++ b/tests/resolvers/Chat/organization.spec.ts @@ -0,0 +1,51 @@ +import "dotenv/config"; +import { organization as organizationResolver } from "../../../src/resolvers/Chat/organization"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { Organization } 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(); + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Chat -> organization", () => { + it(`returns user object for parent.users`, async () => { + const parent = testChat?.toObject(); + if (!parent) { + throw new Error("Parent object is undefined."); + } + + const organizationPayload = await organizationResolver?.(parent, {}, {}); + + const organization = await Organization.findOne({ + _id: { + $in: testChat?.organization, + }, + }).lean(); + + expect(organizationPayload).toEqual(organization); + }); + it(`returns user objects for parent.organization from cache`, async () => { + const parent = testChat?.toObject(); + if (parent) { + const organizationPayload = await organizationResolver?.(parent, {}, {}); + const organization = await Organization.findOne({ + _id: testChat?.organization, + }).lean(); + + expect(organizationPayload).toEqual(organization); + } + }); +}); diff --git a/tests/resolvers/Chat/users.spec.ts b/tests/resolvers/Chat/users.spec.ts index 06ca8e3ada..541b02b497 100644 --- a/tests/resolvers/Chat/users.spec.ts +++ b/tests/resolvers/Chat/users.spec.ts @@ -1,5 +1,5 @@ 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"; 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); - }); -}); From 46d4f5ffd7bc5233ec54d22a943c6dcdc522b8a7 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 18 Aug 2024 19:25:11 +0530 Subject: [PATCH 35/50] Removed unwanted code --- docker-compose.dev.yaml | 2 +- schema.graphql | 78 +++-- src/resolvers/Mutation/adminRemoveGroup.ts | 132 --------- src/resolvers/Mutation/index.ts | 4 - .../Mutation/removeUserFromGroupChat.ts | 96 ------ src/resolvers/Subscription/index.ts | 4 - .../Subscription/messageSentToDirectChat.ts | 36 --- .../Subscription/messageSentToGroupChat.ts | 52 ---- .../groupChatMessageBelongsTo.spec.ts | 65 ----- .../GroupChatMessage/replyTo.spec.ts | 64 ---- .../resolvers/GroupChatMessage/sender.spec.ts | 64 ---- .../Mutation/addUserToGroupChat.spec.ts | 274 ------------------ .../Mutation/adminRemoveGroup.spec.ts | 227 --------------- .../Mutation/createGroupChat.spec.ts | 110 ------- .../Mutation/removeDirectChat.spec.ts | 228 --------------- .../Mutation/removeUserFromGroupChat.spec.ts | 228 --------------- .../Mutation/sendMessageToDirectChat.spec.ts | 178 ------------ .../Mutation/sendMessageToGroupChat.spec.ts | 170 ----------- tests/resolvers/Query/directChatById.spec.ts | 58 ---- .../Query/directChatsByUserID.spec.ts | 58 ---- .../Query/directChatsMessagesByChatID.spec.ts | 96 ------ tests/resolvers/Query/groupChatById.spec.ts | 61 ---- .../Query/groupChatsByUserId.spec.ts | 58 ---- .../messageSentToDirectChat.spec.ts | 103 ------- .../messageSentToGroupChat.spec.ts | 83 ------ 25 files changed, 39 insertions(+), 2490 deletions(-) delete mode 100644 src/resolvers/Mutation/adminRemoveGroup.ts delete mode 100644 src/resolvers/Mutation/removeUserFromGroupChat.ts delete mode 100644 src/resolvers/Subscription/messageSentToDirectChat.ts delete mode 100644 src/resolvers/Subscription/messageSentToGroupChat.ts delete mode 100644 tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts delete mode 100644 tests/resolvers/GroupChatMessage/replyTo.spec.ts delete mode 100644 tests/resolvers/GroupChatMessage/sender.spec.ts delete mode 100644 tests/resolvers/Mutation/addUserToGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/adminRemoveGroup.spec.ts delete mode 100644 tests/resolvers/Mutation/createGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/removeDirectChat.spec.ts delete mode 100644 tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts delete mode 100644 tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts delete mode 100644 tests/resolvers/Query/directChatById.spec.ts delete mode 100644 tests/resolvers/Query/directChatsByUserID.spec.ts delete mode 100644 tests/resolvers/Query/directChatsMessagesByChatID.spec.ts delete mode 100644 tests/resolvers/Query/groupChatById.spec.ts delete mode 100644 tests/resolvers/Query/groupChatsByUserId.spec.ts delete mode 100644 tests/resolvers/Subscription/messageSentToDirectChat.spec.ts delete mode 100644 tests/resolvers/Subscription/messageSentToGroupChat.spec.ts diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 056cb62125..02f8cbfa9a 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -28,7 +28,7 @@ services: - mongodb - redis-stack-server environment: - - mongodb://localhost:27017/talawa-api + - MONGO_DB_URL=mongodb://mongodb:27017 - REDIS_HOST=redis-stack-server - REDIS_PORT=6379 diff --git a/schema.graphql b/schema.graphql index 7a3b9f1d27..cf4050e954 100644 --- a/schema.graphql +++ b/schema.graphql @@ -176,6 +176,33 @@ input CampaignWhereInput { name_contains: String } +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! + type: String! + updatedAt: DateTime! +} + type CheckIn { _id: ID! createdAt: DateTime! @@ -550,36 +577,11 @@ type DirectChatMessage { directChatMessageBelongsTo: DirectChat! messageContent: String! receiver: User! + replyTo: DirectChatMessage sender: User! updatedAt: DateTime! } -type Chat { - _id: ID! - isGroup: Boolean - name: String - createdAt: DateTime! - creator: User - messages: [ChatMessage] - organization: Organization - updatedAt: DateTime! - users: [User!]! - admins: [User] - lastMessageId: String -} - -type ChatMessage { - _id: ID! - createdAt: DateTime! - chatMessageBelongsTo: Chat! - messageContent: String! - type: String! - replyTo: ChatMessage - sender: User! - deletedBy: [User] - updatedAt: DateTime! -} - type Donation { _id: ID! amount: Float! @@ -951,6 +953,7 @@ type GroupChatMessage { createdAt: DateTime! groupChatMessageBelongsTo: GroupChat! messageContent: String! + replyTo: GroupChatMessage sender: User! updatedAt: DateTime! } @@ -1099,9 +1102,8 @@ type Mutation { createAgendaCategory(input: CreateAgendaCategoryInput!): AgendaCategory! createAgendaItem(input: CreateAgendaItemInput!): AgendaItem! createAgendaSection(input: CreateAgendaSectionInput!): AgendaSection! - createComment(data: CommentInput!, postId: ID!): Comment - createDirectChat(data: createChatInput!): DirectChat! createChat(data: chatInput!): Chat + createComment(data: CommentInput!, postId: ID!): Comment createDonation(amount: Float!, nameOfOrg: String!, nameOfUser: String!, orgId: ID!, payPalId: ID!, userId: ID!): Donation! createEvent(data: EventInput!, recurrenceRuleData: RecurrenceRuleInput): Event! createEventVolunteer(data: EventVolunteerInput!): EventVolunteer! @@ -1171,9 +1173,9 @@ type Mutation { revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! - sendMessageToChat(chatId: ID!, messageContent: String!, type: String!, replyTo: ID): ChatMessage! + sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID, type: String!): ChatMessage! sendMessageToDirectChat(chatId: ID!, messageContent: String!, replyTo: ID): DirectChatMessage! - sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage! + sendMessageToGroupChat(chatId: ID!, messageContent: String!, replyTo: ID): GroupChatMessage! signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! unassignUserTag(input: ToggleUserTagAssignInput!): User @@ -1493,11 +1495,12 @@ 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] - chatById(id: ID!): Chat! - chatsByUserId(id: ID!): [Chat] + directChatById(id: ID!): DirectChat directChatsByUserID(id: ID!): [DirectChat] directChatsMessagesByChatID(id: ID!): [DirectChatMessage] event(id: ID!): Event @@ -1626,8 +1629,8 @@ enum Status { type Subscription { directMessageChat: MessageChat - messageSentToDirectChat(userId: ID!): DirectChatMessage messageSentToChat(userId: ID!): ChatMessage + messageSentToDirectChat(userId: ID!): DirectChatMessage messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } @@ -2042,17 +2045,12 @@ enum WeekDays { WEDNESDAY } -input createChatInput { - organizationId: ID - userIds: [ID!]! -} - input chatInput { + image: String isGroup: Boolean! + name: String organizationId: ID userIds: [ID!]! - name: String - image: String } type createDirectChatPayload { 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/index.ts b/src/resolvers/Mutation/index.ts index 1f616cda32..ab7edc7271 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -8,7 +8,6 @@ import { addOrganizationImage } from "./addOrganizationImage"; import { addUserCustomData } from "./addUserCustomData"; import { addUserImage } from "./addUserImage"; import { addUserToUserFamily } from "./addUserToUserFamily"; -import { adminRemoveGroup } from "./adminRemoveGroup"; import { assignUserTag } from "./assignUserTag"; import { blockPluginCreationBySuperadmin } from "./blockPluginCreationBySuperadmin"; import { blockUser } from "./blockUser"; @@ -78,7 +77,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"; @@ -128,7 +126,6 @@ export const Mutation: MutationResolvers = { addOrganizationImage, addUserCustomData, addUserImage, - adminRemoveGroup, addUserToUserFamily, removeUserFamily, removeUserFromUserFamily, @@ -200,7 +197,6 @@ export const Mutation: MutationResolvers = { removeSampleOrganization, removePost, removeUserCustomData, - removeUserFromGroupChat, removeUserImage, removeUserTag, resetCommunity, 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/Subscription/index.ts b/src/resolvers/Subscription/index.ts index 9e9e380a09..703675a2d7 100644 --- a/src/resolvers/Subscription/index.ts +++ b/src/resolvers/Subscription/index.ts @@ -1,13 +1,9 @@ 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/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/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/replyTo.spec.ts b/tests/resolvers/GroupChatMessage/replyTo.spec.ts deleted file mode 100644 index 908f2af1a3..0000000000 --- a/tests/resolvers/GroupChatMessage/replyTo.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import { replyTo as replyToResolver } from "../../../src/resolvers/GroupChatMessage/replyTo"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChatMessage } from "../../../src/models"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import type { TestGroupChatMessageType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { MESSAGE_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 -> replyTo", () => { - it(`returns groupChatMessageBelongsTo object for parent.groupChatMessageBelongsTo`, async () => { - const parent = testGroupChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const replyToPayload = await replyToResolver?.(parent, {}, {}); - - const replyTo = await GroupChatMessage.findOne({ - _id: testGroupChatMessage?.replyTo, - }).lean(); - - expect(replyToPayload).toEqual(replyTo); - }); - it(`throws NotFoundError if no replyTo exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testGroupChatMessage?.toObject(), - reolyTo: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (replyToResolver) { - // @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); - } - }); -}); 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/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/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/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/sendMessageToDirectChat.spec.ts deleted file mode 100644 index 3b589b0226..0000000000 --- a/tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts +++ /dev/null @@ -1,178 +0,0 @@ -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 { connect, disconnect } from "../../helpers/db"; - -import { sendMessageToDirectChat as sendMessageToDirectChatResolver } from "../../../src/resolvers/Mutation/sendMessageToDirectChat"; -import { - CHAT_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - afterEach, - describe, - it, - expect, - vi, -} from "vitest"; -import { createTestUserFunc } from "../../helpers/user"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUsers: TestUserType[]; -let testDirectChat: InterfaceDirectChat & - Document; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const tempUser1 = await createTestUserFunc(); - const tempUser2 = await createTestUserFunc(); - testUsers = [tempUser1, tempUser2]; - - const testOrganization = await Organization.create({ - name: "name", - description: "description", - isPublic: true, - creatorId: testUsers[0]?._id, - admins: [testUsers[0]?._id], - members: [testUsers[0]?._id], - visibleInSearch: true, - }); - - await User.updateOne( - { - _id: testUsers[0]?._id, - }, - { - $set: { - createdOrganizations: [testOrganization._id], - adminFor: [testOrganization._id], - joinedOrganizations: [testOrganization._id], - }, - }, - ); - - testDirectChat = await DirectChat.create({ - title: "title", - creatorId: testUsers[0]?._id, - organization: testOrganization._id, - users: [testUsers[0]?._id, testUsers[1]?._id], - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { - afterEach(async () => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no directChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToDirectChatArgs = { - chatId: new Types.ObjectId().toString(), - messageContent: "", - }; - - const context = { userId: testUsers[0]?.id }; - - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); - - await sendMessageToDirectChatResolver?.({}, 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: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, - messageContent: "", - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); - - await sendMessageToDirectChatResolver?.({}, 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 directChatMessage and returns it`, async () => { - await DirectChat.updateOne( - { - _id: testDirectChat._id, - }, - { - $push: { - users: testUsers[0]?._id, - }, - }, - ); - - const args: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, - messageContent: "messageContent", - }; - - const pubsub = { - publish: ( - _action: "MESSAGE_SENT_TO_DIRECT_CHAT", - _payload: { - messageSentToDirectChat: InterfaceDirectChatMessage; - }, - ): { - _action: string; - _payload: { messageSentToDirectChat: InterfaceDirectChatMessage }; - } => { - return { _action, _payload }; - }, - }; - - const context = { - userId: testUsers[0]?.id, - pubsub, - }; - - const sendMessageToDirectChatPayload = - await sendMessageToDirectChatResolver?.({}, args, context); - - expect(sendMessageToDirectChatPayload).toEqual( - expect.objectContaining({ - directChatMessageBelongsTo: testDirectChat._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/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts deleted file mode 100644 index 0b6e993df1..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, - }; - - 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 770557a301..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, - }; - - 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/messageSentToDirectChat.spec.ts b/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts deleted file mode 100644 index 8a6fdff245..0000000000 --- a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -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 { TestUserType } from "../../helpers/userAndOrg"; -import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToDirectChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testDirectChatMessage: TestDirectChatMessageType; -let testCurrentUser: TestUserType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChatMessage(); - testCurrentUser = resultArray[0]; - testDirectChatMessage = resultArray[3]; -}); -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { - it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { - const { messageSentToDirectChat: messageSentToDirectChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToDirectChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testCurrentUser?._id }, - }; - const variables = { - userId: testCurrentUser?._id, - }; - const payload = { - messageSentToDirectChat: { - receiver: testDirectChatMessage?.receiver, - sender: testDirectChatMessage?.sender, - }, - }; - // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.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 _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testCurrentUser?._id }, - }; - const variables = { - userId: testCurrentUser?._id, - }; - - const payload = { - messageSentToDirectChat: { - receiver: "Receiver", - sender: "Sender", - }, - }; - // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.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); - }); -}); From dcd6006ba0b94e1f3e4cedc311ef61ac80be23a5 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 18 Aug 2024 19:37:49 +0530 Subject: [PATCH 36/50] fix: lint errors --- src/models/Chat.ts | 4 ++-- src/models/ChatMessage.ts | 2 +- tests/resolvers/ChatMessage/replyTo.spec.ts | 5 ----- tests/resolvers/Subscription/messageSentToChat.spec.ts | 1 - 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/models/Chat.ts b/src/models/Chat.ts index fd0c289dba..c5c489eb23 100644 --- a/src/models/Chat.ts +++ b/src/models/Chat.ts @@ -3,14 +3,14 @@ import { Schema, model, models } from "mongoose"; import type { InterfaceOrganization } from "./Organization"; import type { InterfaceUser } from "./User"; import { createLoggingMiddleware } from "../libraries/dbLogger"; -import { InterfaceChatMessage } from "./ChatMessage"; +import type { InterfaceChatMessage } from "./ChatMessage"; /** * Interface representing a document for direct chat in MongoDB. */ export interface InterfaceChat { _id: Types.ObjectId; isGroup: boolean; - name: String; + name: string; users: PopulatedDoc[]; messages: PopulatedDoc[]; creatorId: PopulatedDoc; diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts index f4a7680b7c..724bc44573 100644 --- a/src/models/ChatMessage.ts +++ b/src/models/ChatMessage.ts @@ -2,7 +2,7 @@ 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 { InterfaceChat } from "./Chat"; +import type { InterfaceChat } from "./Chat"; /** * Represents a document for a direct chat message in the MongoDB database. diff --git a/tests/resolvers/ChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts index 7788264f6a..1955f3aaac 100644 --- a/tests/resolvers/ChatMessage/replyTo.spec.ts +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -76,11 +76,6 @@ describe("resolvers -> DirectChatMessage -> replyTo", () => { } }); it(`return null if no replyTo`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - const parent = testChatMessageWithoutReply?.toObject(); if (!parent) { diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts index 14daf9413f..d1c0ab26f5 100644 --- a/tests/resolvers/Subscription/messageSentToChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -6,7 +6,6 @@ import type { TestChatMessageType } from "../../helpers/chat"; import { createTestChatMessage } from "../../helpers/chat"; import type { TestUserType } from "../../helpers/userAndOrg"; import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToChat"; -import { chatMessageBelongsTo } from "../../../src/resolvers/ChatMessage/chatMessageBelongsTo"; let MONGOOSE_INSTANCE: typeof mongoose; let testChatMessage: TestChatMessageType; From a440bad0dd36f7744c045af4fff619de448ffc25 Mon Sep 17 00:00:00 2001 From: Disha Date: Fri, 23 Aug 2024 13:46:16 +0530 Subject: [PATCH 37/50] fix: chat documentation --- src/models/Chat.ts | 6 +++++- src/models/ChatMessage.ts | 6 ++++-- src/resolvers/Chat/admins.ts | 2 +- src/resolvers/Chat/creator.ts | 2 +- src/resolvers/Chat/messages.ts | 2 +- src/resolvers/Chat/organization.ts | 2 +- src/resolvers/Chat/users.ts | 2 +- src/resolvers/ChatMessage/chatMessageBelongsTo.ts | 4 ++-- src/resolvers/ChatMessage/replyTo.ts | 4 ++-- src/resolvers/ChatMessage/sender.ts | 2 +- src/resolvers/Mutation/createChat.ts | 4 ++-- src/resolvers/Mutation/sendMessageToChat.ts | 4 ++-- src/resolvers/Query/chatById.ts | 6 +++--- src/resolvers/Query/chatsByUserId.ts | 2 +- src/resolvers/Subscription/messageSentToChat.ts | 2 +- 15 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/models/Chat.ts b/src/models/Chat.ts index c5c489eb23..813cd539d4 100644 --- a/src/models/Chat.ts +++ b/src/models/Chat.ts @@ -23,14 +23,18 @@ export interface InterfaceChat { } /** - * 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 chatSchema = new Schema( { diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts index 724bc44573..b200e4da41 100644 --- a/src/models/ChatMessage.ts +++ b/src/models/ChatMessage.ts @@ -22,11 +22,13 @@ export interface InterfaceChatMessage { /** * Mongoose schema definition for a direct chat message document. - * @param directChatMessageBelongsTo - Reference to the direct chat session to which the message belongs. + * @param chatMessageBelongsTo - Reference to the 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 replyTo - Reference to the message replied to. + * @param type - Type of the message (STRING, MEDIA, FILE). * @param status - Status of the message (ACTIVE, BLOCKED, DELETED). + * @param deletedBy - List of users who have deleted the message. * @param createdAt - Date when the direct chat message was created. * @param updatedAt - Date when the direct chat message was last updated. */ diff --git a/src/resolvers/Chat/admins.ts b/src/resolvers/Chat/admins.ts index 79b0be4684..a1028aa4e2 100644 --- a/src/resolvers/Chat/admins.ts +++ b/src/resolvers/Chat/admins.ts @@ -1,7 +1,7 @@ import { User } from "../../models"; 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 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. */ diff --git a/src/resolvers/Chat/creator.ts b/src/resolvers/Chat/creator.ts index 795752c870..8d76e1ec3b 100644 --- a/src/resolvers/Chat/creator.ts +++ b/src/resolvers/Chat/creator.ts @@ -1,7 +1,7 @@ import { User } from "../../models"; 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. */ diff --git a/src/resolvers/Chat/messages.ts b/src/resolvers/Chat/messages.ts index 12cb4178ab..db16a74708 100644 --- a/src/resolvers/Chat/messages.ts +++ b/src/resolvers/Chat/messages.ts @@ -1,7 +1,7 @@ import { ChatMessage } from "../../models"; import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the list of all messages in specified Direct Chat from database. + * 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. */ diff --git a/src/resolvers/Chat/organization.ts b/src/resolvers/Chat/organization.ts index a3bec56002..b5692d9392 100644 --- a/src/resolvers/Chat/organization.ts +++ b/src/resolvers/Chat/organization.ts @@ -4,7 +4,7 @@ import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrgani import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; 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. */ diff --git a/src/resolvers/Chat/users.ts b/src/resolvers/Chat/users.ts index 00c126838f..3912780779 100644 --- a/src/resolvers/Chat/users.ts +++ b/src/resolvers/Chat/users.ts @@ -1,7 +1,7 @@ import { User } from "../../models"; 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. */ diff --git a/src/resolvers/ChatMessage/chatMessageBelongsTo.ts b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts index a41878a671..bdd5277b6b 100644 --- a/src/resolvers/ChatMessage/chatMessageBelongsTo.ts +++ b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts @@ -3,9 +3,9 @@ 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 Direct chat to which the specified message belongs. + * 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 Direct chat data. + * @returns An `object` that contains the Chat data. */ export const chatMessageBelongsTo: ChatMessageResolvers["chatMessageBelongsTo"] = async (parent) => { diff --git a/src/resolvers/ChatMessage/replyTo.ts b/src/resolvers/ChatMessage/replyTo.ts index 971e59503f..ff2dc872bb 100644 --- a/src/resolvers/ChatMessage/replyTo.ts +++ b/src/resolvers/ChatMessage/replyTo.ts @@ -3,9 +3,9 @@ import { ChatMessage } from "../../models"; import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; import { errors, requestContext } from "../../libraries"; /** - * This resolver function will fetch and return the receiver(user) of the Direct chat from the database. + * 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 User's data. + * @returns An `object` that contains reply Message's data. */ export const replyTo: ChatMessageResolvers["replyTo"] = async (parent) => { if (parent.replyTo) { diff --git a/src/resolvers/ChatMessage/sender.ts b/src/resolvers/ChatMessage/sender.ts index 8e7280b739..c318fdd7ae 100644 --- a/src/resolvers/ChatMessage/sender.ts +++ b/src/resolvers/ChatMessage/sender.ts @@ -3,7 +3,7 @@ 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 Direct chat from the database. + * 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. */ diff --git a/src/resolvers/Mutation/createChat.ts b/src/resolvers/Mutation/createChat.ts index 033872bdcd..05b3f81124 100644 --- a/src/resolvers/Mutation/createChat.ts +++ b/src/resolvers/Mutation/createChat.ts @@ -8,14 +8,14 @@ import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrgani import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; /** - * This function enables to create a group chat. + * 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 group chat + * @returns Created chat */ export const createChat: MutationResolvers["createChat"] = async ( _parent, diff --git a/src/resolvers/Mutation/sendMessageToChat.ts b/src/resolvers/Mutation/sendMessageToChat.ts index 591cd1bb9e..dd56845294 100644 --- a/src/resolvers/Mutation/sendMessageToChat.ts +++ b/src/resolvers/Mutation/sendMessageToChat.ts @@ -3,14 +3,14 @@ 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 direct chat. + * 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 Direct chat message. + * @returns Chat message. */ export const sendMessageToChat: MutationResolvers["sendMessageToChat"] = async ( _parent, diff --git a/src/resolvers/Query/chatById.ts b/src/resolvers/Query/chatById.ts index bc79b1e946..81fe769977 100644 --- a/src/resolvers/Query/chatById.ts +++ b/src/resolvers/Query/chatById.ts @@ -3,11 +3,11 @@ import { errors } from "../../libraries"; import { Chat } from "../../models"; import { CHAT_NOT_FOUND_ERROR } from "../../constants"; /** - * This query will fetch all the Direct chats for the current user from the database. + * 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 `directChats` that contains all direct chats of the current user. - * If the `directChats` object is null then it throws `NotFoundError` error. + * @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}. */ diff --git a/src/resolvers/Query/chatsByUserId.ts b/src/resolvers/Query/chatsByUserId.ts index 23b2f8bb09..57945ad2f6 100644 --- a/src/resolvers/Query/chatsByUserId.ts +++ b/src/resolvers/Query/chatsByUserId.ts @@ -1,7 +1,7 @@ import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; import { Chat } from "../../models"; /** - * This query will fetch all the Direct chats for the current user from the database. + * 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. diff --git a/src/resolvers/Subscription/messageSentToChat.ts b/src/resolvers/Subscription/messageSentToChat.ts index a48a65d0b6..2da2402c37 100644 --- a/src/resolvers/Subscription/messageSentToChat.ts +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -27,7 +27,7 @@ export const filterFunction = async function ( }; /** * This property included a `subscribe` method, which is used to - * subscribe the `receiver` and `sender` to receive Direct Chat updates. + * 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. From c2d831a11b16fb7bd860c18954817543dabfd99a Mon Sep 17 00:00:00 2001 From: Disha Date: Sat, 24 Aug 2024 16:02:33 +0530 Subject: [PATCH 38/50] added test cases --- tests/resolvers/Mutation/createChat.spec.ts | 26 +++++++++ tests/resolvers/Query/chatById.spec.ts | 34 ++++++++++++ tests/resolvers/Query/chatsByuserId.spec.ts | 58 +++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 tests/resolvers/Query/chatById.spec.ts create mode 100644 tests/resolvers/Query/chatsByuserId.spec.ts diff --git a/tests/resolvers/Mutation/createChat.spec.ts b/tests/resolvers/Mutation/createChat.spec.ts index d9a900f6dd..e7b73539bf 100644 --- a/tests/resolvers/Mutation/createChat.spec.ts +++ b/tests/resolvers/Mutation/createChat.spec.ts @@ -125,4 +125,30 @@ describe("resolvers -> Mutation -> createChat", () => { }), ); }); + + 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(createChatPayload).toEqual( + expect.objectContaining({ + creatorId: testUser?._id, + users: [testUser?._id], + }), + ); + }); }); diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts new file mode 100644 index 0000000000..3461f62272 --- /dev/null +++ b/tests/resolvers/Query/chatById.spec.ts @@ -0,0 +1,34 @@ +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, + }; + const chatByIdPayload = await chatById?.({}, args, {}); + expect(chatByIdPayload).toEqual(testChat?.toObject()); + }); + it(`returns null if fund not found for args.id`, async () => { + const args = { + id: new Types.ObjectId().toString(), + }; + const chatByIdPayload = await chatById?.({}, args, {}); + expect(chatByIdPayload).toEqual({}); + }); +}); diff --git a/tests/resolvers/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts new file mode 100644 index 0000000000..f4716ecec7 --- /dev/null +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -0,0 +1,58 @@ +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 { QueryDirectChatsByUserIdArgs } 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 directChats exists with directChats.users + containing user with _id === args.id`, async () => { + try { + const args: QueryDirectChatsByUserIdArgs = { + id: new Types.ObjectId().toString(), + }; + + await chatsByUserIdResolver?.({}, 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 chatsByUserIdPayload = await chatsByUserIdResolver?.( + {}, + args, + {}, + ); + + const chatsByUserId = await Chat.find({ + users: testUser?._id, + }).lean(); + + expect(chatsByUserIdPayload).toEqual(chatsByUserId); + }); +}); \ No newline at end of file From a2e5141662072cb2f918b4718eb92d4ddc816505 Mon Sep 17 00:00:00 2001 From: Disha Date: Sat, 24 Aug 2024 16:06:49 +0530 Subject: [PATCH 39/50] fix: formatting issues --- tests/resolvers/Query/chatsByuserId.spec.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/resolvers/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts index f4716ecec7..7eeb395962 100644 --- a/tests/resolvers/Query/chatsByuserId.spec.ts +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -43,11 +43,7 @@ describe("resolvers -> Query -> chatsByUserId", () => { id: testUser?._id, }; - const chatsByUserIdPayload = await chatsByUserIdResolver?.( - {}, - args, - {}, - ); + const chatsByUserIdPayload = await chatsByUserIdResolver?.({}, args, {}); const chatsByUserId = await Chat.find({ users: testUser?._id, @@ -55,4 +51,4 @@ describe("resolvers -> Query -> chatsByUserId", () => { expect(chatsByUserIdPayload).toEqual(chatsByUserId); }); -}); \ No newline at end of file +}); From 39d908661a47b7819b9d12640f5e3ebe3960c28e Mon Sep 17 00:00:00 2001 From: Disha Date: Sat, 24 Aug 2024 17:16:46 +0530 Subject: [PATCH 40/50] fix: failed test cases --- tests/resolvers/Query/chatById.spec.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts index 3461f62272..5d59d2c164 100644 --- a/tests/resolvers/Query/chatById.spec.ts +++ b/tests/resolvers/Query/chatById.spec.ts @@ -24,11 +24,14 @@ describe("resolvers->Query->chatById", () => { const chatByIdPayload = await chatById?.({}, args, {}); expect(chatByIdPayload).toEqual(testChat?.toObject()); }); - it(`returns null if fund not found for args.id`, async () => { - const args = { - id: new Types.ObjectId().toString(), - }; - const chatByIdPayload = await chatById?.({}, args, {}); - expect(chatByIdPayload).toEqual({}); + it(`throws chat not found if fund 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"); + } }); }); From 50d579e5a0c8fea2ab2bfbdea5d32ff9c65d16e3 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 22 Sep 2024 14:28:25 +0530 Subject: [PATCH 41/50] fix: failling tests --- src/resolvers/Subscription/messageSentToChat.ts | 4 ++-- tests/helpers/chat.ts | 8 +++++--- tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts | 2 +- tests/resolvers/ChatMessage/replyTo.spec.ts | 2 +- tests/resolvers/Query/chatById.spec.ts | 2 +- tests/resolvers/Subscription/messageSentToChat.spec.ts | 4 ++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/resolvers/Subscription/messageSentToChat.ts b/src/resolvers/Subscription/messageSentToChat.ts index 2da2402c37..99f9978ad8 100644 --- a/src/resolvers/Subscription/messageSentToChat.ts +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -6,8 +6,8 @@ const MESSAGE_SENT_TO_CHAT = "MESSAGE_SENT_TO_CHAT"; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const filterFunction = async function ( - payload: any, - variables: any, + payload: { messageSentToChat: { chatMessageBelongsTo: string } }, + variables: { userId: string }, ): Promise { const currentUserId = variables.userId.toString(); const chatId = payload.messageSentToChat.chatMessageBelongsTo; diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 71511712ef..1e07be9c85 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -6,7 +6,7 @@ import { createTestUserAndOrganization } from "./userAndOrg"; import type { Document } from "mongoose"; export type TestChatType = - | (InterfaceChat & Document) + | (InterfaceChat & Document) | null; export type TestChatMessageType = @@ -38,9 +38,11 @@ export const createTestChatMessage = async (): Promise< [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] > => { const [testUser, testOrganization, testChat] = await createTestChat(); - console.log("TEST CHAT", testChat); - const chatMessage = await createChatMessage(testUser?._id, testChat?._id); + const chatMessage = await createChatMessage( + String(testUser?._id), + String(testChat?._id), + ); if (testChat && testUser) { const testChatMessage = await ChatMessage.create({ diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts index 5b85bea6fb..b3146fb739 100644 --- a/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts @@ -50,7 +50,7 @@ describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { const { requestContext } = await import("../../../src/libraries"); const spy = vi .spyOn(requestContext, "translate") - .mockImplementationOnce((message: any) => message); + .mockImplementationOnce((message: string) => message); const parent = { ...testChatMessage?.toObject(), diff --git a/tests/resolvers/ChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts index 1955f3aaac..c7ad095b73 100644 --- a/tests/resolvers/ChatMessage/replyTo.spec.ts +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -52,7 +52,7 @@ describe("resolvers -> DirectChatMessage -> replyTo", () => { const { requestContext } = await import("../../../src/libraries"); const spy = vi .spyOn(requestContext, "translate") - .mockImplementationOnce((message: any) => message); + .mockImplementationOnce((message: string) => message); const parent = { ...testChatMessage?.toObject(), diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts index 5d59d2c164..a6539702d8 100644 --- a/tests/resolvers/Query/chatById.spec.ts +++ b/tests/resolvers/Query/chatById.spec.ts @@ -19,7 +19,7 @@ afterAll(async () => { describe("resolvers->Query->chatById", () => { it(`returns the chat with _id === args.id`, async () => { const args = { - id: testChat?._id, + id: testChat?._id?.toString() ?? "", }; const chatByIdPayload = await chatById?.({}, args, {}); expect(chatByIdPayload).toEqual(testChat?.toObject()); diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts index d1c0ab26f5..3279a7f86c 100644 --- a/tests/resolvers/Subscription/messageSentToChat.spec.ts +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -42,7 +42,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { }; const payload = { messageSentToChat: { - chatMessageBelongsTo: testChatMessage?.chatMessageBelongsTo, + chatMessageBelongsTo: testChatMessage?.chatMessageBelongsTo as string, }, }; // @ts-expect-error-ignore @@ -74,7 +74,7 @@ describe("src -> resolvers -> Subscription -> messageSentToChat", () => { const payload = { messageSentToChat: { - sender: "Sender", + chatMessageBelongsTo: "vqhgjhShja", }, }; // @ts-expect-error-ignore From 99a24c24c14fed1d5cf4564335482f233cb21319 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 22 Sep 2024 14:53:11 +0530 Subject: [PATCH 42/50] removed unwanted code --- schema.graphql | 48 ---- src/models/ChatMessage.ts | 6 - src/resolvers/Mutation/createMessageChat.ts | 127 --------- src/resolvers/Mutation/index.ts | 2 - src/resolvers/Mutation/sendMessageToChat.ts | 1 - .../Subscription/directMessageChat.ts | 19 -- src/resolvers/Subscription/index.ts | 2 - src/typeDefs/mutations.ts | 26 -- src/typeDefs/queries.ts | 10 - src/typeDefs/subscriptions.ts | 3 - src/typeDefs/types.ts | 58 ---- src/types/generatedGraphQLTypes.ts | 267 ------------------ .../Mutation/createMessageChat.spec.ts | 239 ---------------- tests/resolvers/Query/chatsByuserId.spec.ts | 6 +- .../Subscription/directMessageChat.spec.ts | 22 -- 15 files changed, 3 insertions(+), 833 deletions(-) delete mode 100644 src/resolvers/Mutation/createMessageChat.ts delete mode 100644 src/resolvers/Subscription/directMessageChat.ts delete mode 100644 tests/resolvers/Mutation/createMessageChat.spec.ts delete mode 100644 tests/resolvers/Subscription/directMessageChat.spec.ts diff --git a/schema.graphql b/schema.graphql index e1ba9c4c8a..5dc2d22ec9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -213,7 +213,6 @@ type ChatMessage { messageContent: String! replyTo: ChatMessage sender: User! - type: String! updatedAt: DateTime! } @@ -576,27 +575,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! - replyTo: DirectChatMessage - sender: User! - updatedAt: DateTime! -} - type Donation { _id: ID! amount: Float! @@ -960,27 +938,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! - replyTo: GroupChatMessage - sender: User! - updatedAt: DateTime! -} - type InvalidCursor implements FieldError { message: String! path: [String!]! @@ -1195,8 +1152,6 @@ type Mutation { saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID, type: String!): ChatMessage! - sendMessageToDirectChat(chatId: ID!, messageContent: String!, replyTo: ID): DirectChatMessage! - sendMessageToGroupChat(chatId: ID!, messageContent: String!, replyTo: ID): GroupChatMessage! signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! unassignUserTag(input: ToggleUserTagAssignInput!): User @@ -1530,7 +1485,6 @@ type Query { 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] @@ -1662,8 +1616,6 @@ enum Status { type Subscription { directMessageChat: MessageChat messageSentToChat(userId: ID!): ChatMessage - messageSentToDirectChat(userId: ID!): DirectChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts index b200e4da41..a5121f6d51 100644 --- a/src/models/ChatMessage.ts +++ b/src/models/ChatMessage.ts @@ -13,7 +13,6 @@ export interface InterfaceChatMessage { sender: PopulatedDoc; replyTo: PopulatedDoc; messageContent: string; - type: string; status: string; deletedBy: PopulatedDoc[]; createdAt: Date; @@ -53,11 +52,6 @@ const chatMessageSchema = new Schema( type: String, required: true, }, - type: { - type: String, - required: true, - enum: ["STRING", "VIDEO", "IMAGE", "FILE"], - }, status: { type: String, required: true, 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 b22f926f90..995f77481c 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -31,7 +31,6 @@ import { createFundraisingCampaign } from "./createFundraisingCampaign"; import { createEventVolunteerGroup } from "./createEventVolunteerGroup"; import { createFundraisingCampaignPledge } from "./createFundraisingCampaignPledge"; import { createMember } from "./createMember"; -import { createMessageChat } from "./createMessageChat"; import { createOrganization } from "./createOrganization"; import { createPlugin } from "./createPlugin"; import { createPost } from "./createPost"; @@ -148,7 +147,6 @@ export const Mutation: MutationResolvers = { createEvent, createFund, createFundraisingCampaign, - createMessageChat, createOrganization, createNote, createPlugin, diff --git a/src/resolvers/Mutation/sendMessageToChat.ts b/src/resolvers/Mutation/sendMessageToChat.ts index dd56845294..a5c7e83558 100644 --- a/src/resolvers/Mutation/sendMessageToChat.ts +++ b/src/resolvers/Mutation/sendMessageToChat.ts @@ -47,7 +47,6 @@ export const sendMessageToChat: MutationResolvers["sendMessageToChat"] = async ( chatMessageBelongsTo: chat._id, sender: context.userId, messageContent: args.messageContent, - type: args.type, replyTo: args.replyTo, createdAt: now, updatedAt: now, 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 703675a2d7..f2f19e4836 100644 --- a/src/resolvers/Subscription/index.ts +++ b/src/resolvers/Subscription/index.ts @@ -1,9 +1,7 @@ import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; -import { directMessageChat } from "./directMessageChat"; import { messageSentToChat } from "./messageSentToChat"; import { onPluginUpdate } from "./onPluginUpdate"; export const Subscription: SubscriptionResolvers = { - directMessageChat, messageSentToChat, onPluginUpdate, }; diff --git a/src/typeDefs/mutations.ts b/src/typeDefs/mutations.ts index 264d5f06c3..52e6d974ff 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( @@ -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,12 +232,6 @@ export const mutations = gql` sendMembershipRequest(organizationId: ID!): MembershipRequest! @auth - sendMessageToDirectChat( - chatId: ID! - messageContent: String! - replyTo: ID - ): DirectChatMessage! @auth - sendMessageToChat( chatId: ID! messageContent: String! @@ -259,12 +239,6 @@ export const mutations = gql` replyTo: ID ): ChatMessage! @auth - sendMessageToGroupChat( - chatId: ID! - messageContent: String! - replyTo: ID - ): GroupChatMessage! @auth - signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! @auth diff --git a/src/typeDefs/queries.ts b/src/typeDefs/queries.ts index 09a075a429..b4e40c3e6c 100644 --- a/src/typeDefs/queries.ts +++ b/src/typeDefs/queries.ts @@ -48,16 +48,6 @@ export const queries = gql` chatsByUserId(id: ID!): [Chat] - directChatsByUserID(id: ID!): [DirectChat] - - directChatById(id: ID!): DirectChat - - groupChatById(id: ID!): GroupChat - - groupChatsByUserId(id: ID!): [GroupChat] - - directChatsMessagesByChatID(id: ID!): [DirectChatMessage] - event(id: ID!): Event eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] diff --git a/src/typeDefs/subscriptions.ts b/src/typeDefs/subscriptions.ts index 45bc014656..f5e3c89c2b 100644 --- a/src/typeDefs/subscriptions.ts +++ b/src/typeDefs/subscriptions.ts @@ -3,10 +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 messageSentToChat(userId: ID!): ChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage onPluginUpdate: Plugin } `; diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index eb88a14cce..c53266073b 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -164,11 +164,6 @@ export const types = gql` userErrors: [CreateCommentError!]! } - type createDirectChatPayload { - directChat: DirectChat - userErrors: [CreateDirectChatError!]! - } - type DeletePayload { success: Boolean! } @@ -177,27 +172,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! - replyTo: DirectChatMessage - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! - } - type Donation { _id: ID! userId: ID! @@ -373,27 +347,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! - replyTo: GroupChatMessage - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! - } - type Language { _id: ID! en: String! @@ -425,16 +378,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! @@ -795,7 +738,6 @@ export const types = gql` chatMessageBelongsTo: Chat! replyTo: ChatMessage messageContent: String! - type: String! sender: User! deletedBy: [User] updatedAt: DateTime! diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 180b07c447..7f3f3cffff 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -287,7 +287,6 @@ export type ChatMessage = { messageContent: Scalars['String']['output']; replyTo?: Maybe; sender: User; - type: Scalars['String']['output']; updatedAt: Scalars['DateTime']['output']; }; @@ -652,29 +651,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; - replyTo?: Maybe; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type Donation = { __typename?: 'Donation'; _id: Scalars['ID']['output']; @@ -1045,29 +1021,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']; - replyTo?: Maybe; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type InvalidCursor = FieldError & { __typename?: 'InvalidCursor'; message: Scalars['String']['output']; @@ -1160,17 +1113,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']; @@ -1200,9 +1142,7 @@ export type Mutation = { addPledgeToFundraisingCampaign: FundraisingCampaignPledge; addUserCustomData: UserCustomData; addUserImage: User; - addUserToGroupChat: GroupChat; addUserToUserFamily: UserFamily; - adminRemoveGroup: GroupChat; assignUserTag?: Maybe; blockPluginCreationBySuperadmin: AppUserProfile; blockUser: User; @@ -1225,9 +1165,7 @@ export type Mutation = { createFund: Fund; createFundraisingCampaign: FundraisingCampaign; createFundraisingCampaignPledge: FundraisingCampaignPledge; - createGroupChat: GroupChat; createMember: CreateMemberPayload; - createMessageChat: MessageChat; createNote: Note; createOrganization: Organization; createPlugin: Plugin; @@ -1262,13 +1200,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; @@ -1277,7 +1213,6 @@ export type Mutation = { removeSampleOrganization: Scalars['Boolean']['output']; removeUserCustomData: UserCustomData; removeUserFamily: UserFamily; - removeUserFromGroupChat: GroupChat; removeUserFromUserFamily: UserFamily; removeUserImage: User; removeUserTag?: Maybe; @@ -1286,8 +1221,6 @@ export type Mutation = { saveFcmToken: Scalars['Boolean']['output']; sendMembershipRequest: MembershipRequest; sendMessageToChat: ChatMessage; - sendMessageToDirectChat: DirectChatMessage; - sendMessageToGroupChat: GroupChatMessage; signUp: AuthData; togglePostPin: Post; unassignUserTag?: Maybe; @@ -1371,23 +1304,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; }; @@ -1510,21 +1432,11 @@ export type MutationCreateFundraisingCampaignPledgeArgs = { }; -export type MutationCreateGroupChatArgs = { - data: CreateGroupChatInput; -}; - - export type MutationCreateMemberArgs = { input: UserAndOrganizationInput; }; -export type MutationCreateMessageChatArgs = { - data: MessageChatInput; -}; - - export type MutationCreateNoteArgs = { data: NoteInput; }; @@ -1690,12 +1602,6 @@ export type MutationRemoveCommentArgs = { }; -export type MutationRemoveDirectChatArgs = { - chatId: Scalars['ID']['input']; - organizationId: Scalars['ID']['input']; -}; - - export type MutationRemoveEventArgs = { id: Scalars['ID']['input']; recurringEventDeleteType?: InputMaybe; @@ -1722,11 +1628,6 @@ export type MutationRemoveFundraisingCampaignPledgeArgs = { }; -export type MutationRemoveGroupChatArgs = { - chatId: Scalars['ID']['input']; -}; - - export type MutationRemoveMemberArgs = { data: UserAndOrganizationInput; }; @@ -1763,12 +1664,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']; @@ -1798,20 +1693,6 @@ export type MutationSendMessageToChatArgs = { }; -export type MutationSendMessageToDirectChatArgs = { - chatId: Scalars['ID']['input']; - messageContent: Scalars['String']['input']; - replyTo?: InputMaybe; -}; - - -export type MutationSendMessageToGroupChatArgs = { - chatId: Scalars['ID']['input']; - messageContent: Scalars['String']['input']; - replyTo?: InputMaybe; -}; - - export type MutationSignUpArgs = { data: UserInput; file?: InputMaybe; @@ -2321,9 +2202,6 @@ export type Query = { checkAuth: User; customDataByOrganization: Array; customFieldsByOrganization?: Maybe>>; - directChatById?: Maybe; - directChatsByUserID?: Maybe>>; - directChatsMessagesByChatID?: Maybe>>; event?: Maybe; eventVolunteersByEvent?: Maybe>>; eventsByOrganization?: Maybe>>; @@ -2351,8 +2229,6 @@ export type Query = { getUserTagAncestors?: Maybe>>; getVenueByOrgId?: Maybe>>; getlanguage?: Maybe>>; - groupChatById?: Maybe; - groupChatsByUserId?: Maybe>>; hasSubmittedFeedback?: Maybe; isSampleOrganization: Scalars['Boolean']['output']; joinedOrganizations?: Maybe>>; @@ -2446,21 +2322,6 @@ export type QueryCustomFieldsByOrganizationArgs = { }; -export type QueryDirectChatByIdArgs = { - id: Scalars['ID']['input']; -}; - - -export type QueryDirectChatsByUserIdArgs = { - id: Scalars['ID']['input']; -}; - - -export type QueryDirectChatsMessagesByChatIdArgs = { - id: Scalars['ID']['input']; -}; - - export type QueryEventArgs = { id: Scalars['ID']['input']; }; @@ -2601,16 +2462,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']; @@ -2784,10 +2635,7 @@ export type Status = export type Subscription = { __typename?: 'Subscription'; - directMessageChat?: Maybe; messageSentToChat?: Maybe; - messageSentToDirectChat?: Maybe; - messageSentToGroupChat?: Maybe; onPluginUpdate?: Maybe; }; @@ -2796,16 +2644,6 @@ export type SubscriptionMessageSentToChatArgs = { userId: Scalars['ID']['input']; }; - -export type SubscriptionMessageSentToDirectChatArgs = { - userId: Scalars['ID']['input']; -}; - - -export type SubscriptionMessageSentToGroupChatArgs = { - userId: Scalars['ID']['input']; -}; - export type ToggleUserTagAssignInput = { tagId: Scalars['ID']['input']; userId: Scalars['ID']['input']; @@ -3263,12 +3101,6 @@ export type ChatInput = { userIds: Array; }; -export type CreateDirectChatPayload = { - __typename?: 'createDirectChatPayload'; - directChat?: Maybe; - userErrors: Array; -}; - export type CreateGroupChatInput = { organizationId: Scalars['ID']['input']; title: Scalars['String']['input']; @@ -3416,8 +3248,6 @@ export type ResolversTypes = { DefaultConnectionPageInfo: ResolverTypeWrapper; DeleteAdvertisementPayload: ResolverTypeWrapper & { advertisement?: Maybe }>; DeletePayload: ResolverTypeWrapper; - DirectChat: ResolverTypeWrapper & { creator?: Maybe, messages?: Maybe>>, organization?: Maybe, users: Array }>; - DirectChatMessage: ResolverTypeWrapper & { directChatMessageBelongsTo: ResolversTypes['DirectChat'], receiver: ResolversTypes['User'], replyTo?: Maybe, sender: ResolversTypes['User'] }>; Donation: ResolverTypeWrapper; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3454,8 +3284,6 @@ export type ResolversTypes = { FundraisingCampaignPledge: ResolverTypeWrapper; Gender: Gender; Group: ResolverTypeWrapper; - GroupChat: ResolverTypeWrapper & { creator?: Maybe, messages?: Maybe>>, organization: ResolversTypes['Organization'], users: Array }>; - GroupChatMessage: ResolverTypeWrapper & { groupChatMessageBelongsTo: ResolversTypes['GroupChat'], replyTo?: Maybe, sender: ResolversTypes['User'] }>; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; InvalidCursor: ResolverTypeWrapper; @@ -3474,7 +3302,6 @@ export type ResolversTypes = { MembershipRequest: ResolverTypeWrapper; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: ResolverTypeWrapper; - MessageChat: ResolverTypeWrapper; MessageChatInput: MessageChatInput; MinimumLengthError: ResolverTypeWrapper; MinimumValueError: ResolverTypeWrapper; @@ -3573,7 +3400,6 @@ export type ResolversTypes = { VenueWhereInput: VenueWhereInput; WeekDays: WeekDays; chatInput: ChatInput; - createDirectChatPayload: ResolverTypeWrapper & { directChat?: Maybe, userErrors: Array }>; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3631,8 +3457,6 @@ export type ResolversParentTypes = { DefaultConnectionPageInfo: DefaultConnectionPageInfo; DeleteAdvertisementPayload: Omit & { advertisement?: Maybe }; DeletePayload: DeletePayload; - DirectChat: Omit & { creator?: Maybe, messages?: Maybe>>, organization?: Maybe, users: Array }; - DirectChatMessage: Omit & { directChatMessageBelongsTo: ResolversParentTypes['DirectChat'], receiver: ResolversParentTypes['User'], replyTo?: Maybe, sender: ResolversParentTypes['User'] }; Donation: InterfaceDonationModel; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3662,8 +3486,6 @@ export type ResolversParentTypes = { FundraisingCampaign: InterfaceFundraisingCampaignModel; FundraisingCampaignPledge: InterfaceFundraisingCampaignPledgesModel; Group: InterfaceGroupModel; - GroupChat: Omit & { creator?: Maybe, messages?: Maybe>>, organization: ResolversParentTypes['Organization'], users: Array }; - GroupChatMessage: Omit & { groupChatMessageBelongsTo: ResolversParentTypes['GroupChat'], replyTo?: Maybe, sender: ResolversParentTypes['User'] }; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; InvalidCursor: InvalidCursor; @@ -3680,7 +3502,6 @@ export type ResolversParentTypes = { MembershipRequest: InterfaceMembershipRequestModel; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: InterfaceMessageModel; - MessageChat: InterfaceMessageChatModel; MessageChatInput: MessageChatInput; MinimumLengthError: MinimumLengthError; MinimumValueError: MinimumValueError; @@ -3767,7 +3588,6 @@ export type ResolversParentTypes = { VenueInput: VenueInput; VenueWhereInput: VenueWhereInput; chatInput: ChatInput; - createDirectChatPayload: Omit & { directChat?: Maybe, userErrors: Array }; createGroupChatInput: CreateGroupChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3956,7 +3776,6 @@ export type ChatMessageResolvers; replyTo?: Resolver, ParentType, ContextType>; sender?: Resolver; - type?: Resolver; updatedAt?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4090,29 +3909,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; - replyTo?: Resolver, ParentType, ContextType>; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type DonationResolvers = { _id?: Resolver; amount?: Resolver; @@ -4284,29 +4080,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; - replyTo?: Resolver, ParentType, ContextType>; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type InvalidCursorResolvers = { message?: Resolver; path?: Resolver, ParentType, ContextType>; @@ -4378,17 +4151,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; @@ -4412,9 +4174,7 @@ export type MutationResolvers>; addUserCustomData?: Resolver>; addUserImage?: Resolver>; - addUserToGroupChat?: Resolver>; addUserToUserFamily?: Resolver>; - adminRemoveGroup?: Resolver>; assignUserTag?: Resolver, ParentType, ContextType, RequireFields>; blockPluginCreationBySuperadmin?: Resolver>; blockUser?: Resolver>; @@ -4437,9 +4197,7 @@ export type MutationResolvers>; createFundraisingCampaign?: Resolver>; createFundraisingCampaignPledge?: Resolver>; - createGroupChat?: Resolver>; createMember?: Resolver>; - createMessageChat?: Resolver>; createNote?: Resolver>; createOrganization?: Resolver>; createPlugin?: Resolver>; @@ -4474,13 +4232,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>; @@ -4489,7 +4245,6 @@ export type MutationResolvers; removeUserCustomData?: Resolver>; removeUserFamily?: Resolver>; - removeUserFromGroupChat?: Resolver>; removeUserFromUserFamily?: Resolver>; removeUserImage?: Resolver; removeUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4498,8 +4253,6 @@ export type MutationResolvers>; sendMembershipRequest?: Resolver>; sendMessageToChat?: Resolver>; - sendMessageToDirectChat?: Resolver>; - sendMessageToGroupChat?: Resolver>; signUp?: Resolver>; togglePostPin?: Resolver>; unassignUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4691,9 +4444,6 @@ export type QueryResolvers; 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>; @@ -4721,8 +4471,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>; @@ -4770,10 +4518,7 @@ export type SocialMediaUrlsResolvers = { - directMessageChat?: SubscriptionResolver, "directMessageChat", ParentType, ContextType>; messageSentToChat?: SubscriptionResolver, "messageSentToChat", ParentType, ContextType, RequireFields>; - messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType, RequireFields>; - messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType, RequireFields>; onPluginUpdate?: SubscriptionResolver, "onPluginUpdate", ParentType, ContextType>; }; @@ -4938,12 +4683,6 @@ export type VenueResolvers; }; -export type CreateDirectChatPayloadResolvers = { - directChat?: Resolver, ParentType, ContextType>; - userErrors?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type Resolvers = { ActionItem?: ActionItemResolvers; ActionItemCategory?: ActionItemCategoryResolvers; @@ -4982,8 +4721,6 @@ export type Resolvers = { DefaultConnectionPageInfo?: DefaultConnectionPageInfoResolvers; DeleteAdvertisementPayload?: DeleteAdvertisementPayloadResolvers; DeletePayload?: DeletePayloadResolvers; - DirectChat?: DirectChatResolvers; - DirectChatMessage?: DirectChatMessageResolvers; Donation?: DonationResolvers; EmailAddress?: GraphQLScalarType; Error?: ErrorResolvers; @@ -4998,8 +4735,6 @@ export type Resolvers = { FundraisingCampaign?: FundraisingCampaignResolvers; FundraisingCampaignPledge?: FundraisingCampaignPledgeResolvers; Group?: GroupResolvers; - GroupChat?: GroupChatResolvers; - GroupChatMessage?: GroupChatMessageResolvers; InvalidCursor?: InvalidCursorResolvers; JSON?: GraphQLScalarType; Language?: LanguageResolvers; @@ -5011,7 +4746,6 @@ export type Resolvers = { MemberNotFoundError?: MemberNotFoundErrorResolvers; MembershipRequest?: MembershipRequestResolvers; Message?: MessageResolvers; - MessageChat?: MessageChatResolvers; MinimumLengthError?: MinimumLengthErrorResolvers; MinimumValueError?: MinimumValueErrorResolvers; Mutation?: MutationResolvers; @@ -5057,7 +4791,6 @@ export type Resolvers = { UsersConnection?: UsersConnectionResolvers; UsersConnectionEdge?: UsersConnectionEdgeResolvers; Venue?: VenueResolvers; - createDirectChatPayload?: CreateDirectChatPayloadResolvers; }; export type DirectiveResolvers = { 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/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts index 7eeb395962..2f76f3d18f 100644 --- a/tests/resolvers/Query/chatsByuserId.spec.ts +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -5,7 +5,7 @@ import { connect, disconnect } from "../../helpers/db"; import { chatsByUserId as chatsByUserIdResolver } from "../../../src/resolvers/Query/chatsByUserId"; import { Chat } from "../../../src/models"; -import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; +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"; @@ -27,7 +27,7 @@ describe("resolvers -> Query -> chatsByUserId", () => { it(`throws NotFoundError if no directChats exists with directChats.users containing user with _id === args.id`, async () => { try { - const args: QueryDirectChatsByUserIdArgs = { + const args: QueryChatsByUserIdArgs = { id: new Types.ObjectId().toString(), }; @@ -39,7 +39,7 @@ describe("resolvers -> Query -> chatsByUserId", () => { it(`returns list of all directChats with directChat.users containing the user with _id === args.id`, async () => { - const args: QueryDirectChatsByUserIdArgs = { + const args: QueryChatsByUserIdArgs = { id: testUser?._id, }; 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); - }); -}); From 23ba0b510091ce189df82df5a3cd6a5e9dfa1ee3 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Sun, 22 Sep 2024 14:55:59 +0530 Subject: [PATCH 43/50] Update tests/resolvers/Query/chatById.spec.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- tests/resolvers/Query/chatById.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts index a6539702d8..9adb1c22ea 100644 --- a/tests/resolvers/Query/chatById.spec.ts +++ b/tests/resolvers/Query/chatById.spec.ts @@ -24,7 +24,7 @@ describe("resolvers->Query->chatById", () => { const chatByIdPayload = await chatById?.({}, args, {}); expect(chatByIdPayload).toEqual(testChat?.toObject()); }); - it(`throws chat not found if fund not found for args.id`, async () => { + it(`throws chat not found if chat not found for args.id`, async () => { try { const args = { id: new Types.ObjectId().toString(), From c4f6cd67028d2f4c6b49a92fd8385cc1c46411a6 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 22 Sep 2024 15:00:13 +0530 Subject: [PATCH 44/50] fix: removed ignore statements --- src/resolvers/Subscription/messageSentToChat.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/resolvers/Subscription/messageSentToChat.ts b/src/resolvers/Subscription/messageSentToChat.ts index 99f9978ad8..936fd104de 100644 --- a/src/resolvers/Subscription/messageSentToChat.ts +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -4,7 +4,6 @@ import { Chat } from "../../models"; const MESSAGE_SENT_TO_CHAT = "MESSAGE_SENT_TO_CHAT"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export const filterFunction = async function ( payload: { messageSentToChat: { chatMessageBelongsTo: string } }, variables: { userId: string }, From 9f2f12de2798fdfdf42ef9b3d3d522a7619fb771 Mon Sep 17 00:00:00 2001 From: Disha Talreja Date: Sun, 22 Sep 2024 15:10:45 +0530 Subject: [PATCH 45/50] Update schema.graphql Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- schema.graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema.graphql b/schema.graphql index 5dc2d22ec9..4784160d4f 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1615,7 +1615,7 @@ enum Status { type Subscription { directMessageChat: MessageChat - messageSentToChat(userId: ID!): ChatMessage + messageSentToChat(userId: ID!): ChatMessage @auth onPluginUpdate: Plugin } From a6b960f0b415a2c539d813b5b55d1e5eb190e2f1 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 22 Sep 2024 17:39:02 +0530 Subject: [PATCH 46/50] fix: failing tests --- .eslintrc.json | 2 +- setup.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 79ad3ed89a..6f13ff601d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -79,7 +79,7 @@ "plugins": ["@graphql-eslint"] }, { - "files": ["tests/**/*"], + "files": ["tests/**/*", "setup.ts"], "rules": { "no-restricted-imports": "off" } diff --git a/setup.ts b/setup.ts index 3c35fc69d3..329481eda8 100644 --- a/setup.ts +++ b/setup.ts @@ -1,10 +1,8 @@ -// eslint-disable-next-line import * as cryptolib from "crypto"; import dotenv from "dotenv"; import fs from "fs"; import inquirer from "inquirer"; import path from "path"; -/* eslint-disable */ import type { ExecException } from "child_process"; import { exec } from "child_process"; import { MongoClient } from "mongodb"; @@ -31,7 +29,6 @@ import { askForSuperAdminEmail } from "./src/setup/superAdmin"; import { updateEnvVariable } from "./src/setup/updateEnvVariable"; import { verifySmtpConnection } from "./src/setup/verifySmtpConnection"; import { loadDefaultOrganiation } from "./src/utilities/loadDefaultOrg"; -/* eslint-enable */ dotenv.config(); From bf38bc67e9f761a23b8bd67680d398faa9e43316 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 22 Sep 2024 17:44:34 +0530 Subject: [PATCH 47/50] fix: removed eslint disabled statements --- setup.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.ts b/setup.ts index 329481eda8..a068cb2ab9 100644 --- a/setup.ts +++ b/setup.ts @@ -168,7 +168,6 @@ function transactionLogPath(logPath: string | null): void { async function askForTransactionLogPath(): Promise { let logPath: string | null; // Keep asking for path, until user gives a valid path - // eslint-disable-next-line no-constant-condition while (true) { const response = await inquirer.prompt([ { From d42aca68623ca98f78ba20a234affb961720d3eb Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 29 Sep 2024 16:41:59 +0530 Subject: [PATCH 48/50] updated tests and helper functions --- src/models/ChatMessage.ts | 38 ++++++++++----- src/resolvers/Mutation/createChat.ts | 45 +++++++----------- tests/helpers/chat.ts | 37 ++++++++------- tests/resolvers/Chat/admins.spec.ts | 10 ++-- tests/resolvers/Chat/organization.spec.ts | 26 ++++++----- tests/resolvers/ChatMessage/replyTo.spec.ts | 52 +++++++++++++++------ tests/resolvers/Query/chatsByuserId.spec.ts | 6 +-- 7 files changed, 126 insertions(+), 88 deletions(-) diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts index a5121f6d51..1229935834 100644 --- a/src/models/ChatMessage.ts +++ b/src/models/ChatMessage.ts @@ -5,7 +5,7 @@ import { createLoggingMiddleware } from "../libraries/dbLogger"; import type { InterfaceChat } from "./Chat"; /** - * Represents a document for a direct chat message in the MongoDB database. + * Represents a document for a chat message in the MongoDB database. */ export interface InterfaceChatMessage { _id: Types.ObjectId; @@ -20,16 +20,32 @@ export interface InterfaceChatMessage { } /** - * Mongoose schema definition for a direct chat message document. - * @param chatMessageBelongsTo - Reference to the chat session to which the message belongs. - * @param sender - Reference to the user who sent the message. - * @param messageContent - Content of the direct chat message. - * @param replyTo - Reference to the message replied to. - * @param type - Type of the message (STRING, MEDIA, FILE). - * @param status - Status of the message (ACTIVE, BLOCKED, DELETED). - * @param deletedBy - List of users who have deleted the message. - * @param createdAt - Date when the direct chat message was created. - * @param updatedAt - Date when the direct chat message was last updated. + * 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( { diff --git a/src/resolvers/Mutation/createChat.ts b/src/resolvers/Mutation/createChat.ts index 05b3f81124..03615d07d4 100644 --- a/src/resolvers/Mutation/createChat.ts +++ b/src/resolvers/Mutation/createChat.ts @@ -3,8 +3,7 @@ import { USER_NOT_FOUND_ERROR, } from "../../constants"; import { errors, requestContext } from "../../libraries"; -import { Chat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; +import { Chat, User } from "../../models"; import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; /** @@ -23,7 +22,6 @@ export const createChat: MutationResolvers["createChat"] = async ( context, ) => { let organization; - const usersInChat = []; if (args.data.isGroup && args.data.organizationId) { const organizationFoundInCache = await findOrganizationsInCache([ args.data.organizationId, @@ -31,13 +29,6 @@ export const createChat: MutationResolvers["createChat"] = async ( organization = organizationFoundInCache[0]; - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: args.data.organizationId, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - // Checks whether organization with _id === args.data.organizationId exists. if (!organization) { throw new errors.NotFoundError( @@ -48,20 +39,20 @@ export const createChat: MutationResolvers["createChat"] = async ( } } - for await (const userId of args.data.userIds) { - const userExists = !!(await User.exists({ - _id: userId, - })); + const userExists = (await User.exists({ + _id: { $in: args.data.userIds }, + })) as unknown as string[]; - // 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, - ); - } - usersInChat.push(userId); + if (userExists && userExists.length !== args.data.userIds.length) { + // Find which user ID(s) do not exist + const missingUsers = args.data.userIds.filter( + (id) => !userExists.includes(id), + ); + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + JSON.stringify({ missingUsers: missingUsers }), + ); } const now = new Date(); @@ -70,8 +61,8 @@ export const createChat: MutationResolvers["createChat"] = async ( ? { isGroup: args.data.isGroup, creatorId: context.userId, - users: usersInChat, - organization: args.data?.organizationId, + users: args.data.userIds, + organization: args.data.organizationId, name: args.data?.name, admins: [context.userId], createdAt: now, @@ -80,7 +71,7 @@ export const createChat: MutationResolvers["createChat"] = async ( } : { creatorId: context.userId, - users: usersInChat, + users: args.data.userIds, isGroup: args.data.isGroup, createdAt: now, updatedAt: now, @@ -88,5 +79,5 @@ export const createChat: MutationResolvers["createChat"] = async ( const createdChat = await Chat.create(chatPayload); - return createdChat.toObject(); + return createdChat; }; diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts index 1e07be9c85..b3fa7b468a 100644 --- a/tests/helpers/chat.ts +++ b/tests/helpers/chat.ts @@ -39,25 +39,28 @@ export const createTestChatMessage = async (): Promise< > => { const [testUser, testOrganization, testChat] = await createTestChat(); - const chatMessage = await createChatMessage( - String(testUser?._id), - String(testChat?._id), - ); + 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]; + 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< diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts index 575fee42b2..00b752b622 100644 --- a/tests/resolvers/Chat/admins.spec.ts +++ b/tests/resolvers/Chat/admins.spec.ts @@ -12,8 +12,7 @@ let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestChatMessage(); - testChat = userOrgChat[2]; + [, , testChat] = await createTestChatMessage(); }); afterAll(async () => { @@ -21,13 +20,16 @@ afterAll(async () => { }); describe("resolvers -> Chat -> admins", () => { - it(`returns user object for parent.users`, async () => { + it(`resolves the correct admin users for the given chat`, async () => { const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } - const usersPayload = await adminsResolver?.(parent, {}, {}); + if (!adminsResolver) { + throw new Error("adminsResolver is not defined."); + } + const usersPayload = await adminsResolver(parent, {}, {}); const users = await User.find({ _id: { diff --git a/tests/resolvers/Chat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts index 6f413b8f20..f8414b6a74 100644 --- a/tests/resolvers/Chat/organization.spec.ts +++ b/tests/resolvers/Chat/organization.spec.ts @@ -21,7 +21,7 @@ afterAll(async () => { }); describe("resolvers -> Chat -> organization", () => { - it(`returns user object for parent.users`, async () => { + 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,24 @@ describe("resolvers -> Chat -> organization", () => { const organizationPayload = await organizationResolver?.(parent, {}, {}); const organization = await Organization.findOne({ - _id: { - $in: testChat?.organization, - }, + _id: testChat?.organization, }).lean(); expect(organizationPayload).toEqual(organization); }); - it(`returns user objects for parent.organization from cache`, async () => { + it("resolves the organization from cache", async () => { const parent = testChat?.toObject(); - if (parent) { - const organizationPayload = await organizationResolver?.(parent, {}, {}); - const organization = await Organization.findOne({ - _id: testChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); + 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: testChat?.organization, + }).lean(); + + expect(organizationPayload).toEqual(organization); }); }); diff --git a/tests/resolvers/ChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts index c7ad095b73..162c2d2ba8 100644 --- a/tests/resolvers/ChatMessage/replyTo.spec.ts +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -17,20 +17,39 @@ let testChatMessageWithoutReply: TestChatMessageType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestChatMessageWithoutReply(); - const temp1 = await createTestChatMessage(); - testChatMessageWithoutReply = temp[3]; - testChatMessage = temp1[3]; + 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 () => { - await disconnect(MONGOOSE_INSTANCE); + if (MONGOOSE_INSTANCE) { + await disconnect(MONGOOSE_INSTANCE); + } }); describe("resolvers -> DirectChatMessage -> replyTo", () => { it(`returns directChat object for parent.replyTo`, async () => { - const parent = testChatMessage?.toObject(); + const parent = testChatMessage ? testChatMessage.toObject() : null; if (!parent) { throw new Error("Parent object is undefined."); @@ -40,13 +59,16 @@ describe("resolvers -> DirectChatMessage -> replyTo", () => { throw new Error("replyToResolver is not a function."); } - const replyToPayload = await replyToResolver(parent, {}, {}); - - const replyTo = await ChatMessage.findOne({ - _id: testChatMessage?.replyTo, - }).lean(); - - expect(replyToPayload).toEqual(replyTo); + 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"); @@ -73,6 +95,8 @@ describe("resolvers -> DirectChatMessage -> replyTo", () => { } 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 () => { diff --git a/tests/resolvers/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts index 2f76f3d18f..c07ba1dfe2 100644 --- a/tests/resolvers/Query/chatsByuserId.spec.ts +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -24,7 +24,7 @@ afterAll(async () => { }); describe("resolvers -> Query -> chatsByUserId", () => { - it(`throws NotFoundError if no directChats exists with directChats.users + it(`throws NotFoundError if no Chats exists with chats.users containing user with _id === args.id`, async () => { try { const args: QueryChatsByUserIdArgs = { @@ -33,11 +33,11 @@ describe("resolvers -> Query -> chatsByUserId", () => { await chatsByUserIdResolver?.({}, args, {}); } catch (error: unknown) { - expect((error as Error).message).toEqual("DirectChats not found"); + expect((error as Error).message).toEqual("Chats not found"); } }); - it(`returns list of all directChats with directChat.users containing the user + it(`returns list of all chats with chat.users containing the user with _id === args.id`, async () => { const args: QueryChatsByUserIdArgs = { id: testUser?._id, From 7d5667d2c55285bc4fcb9637755a537f2cb5b9a9 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 6 Oct 2024 17:17:48 +0530 Subject: [PATCH 49/50] reverted: unrelated changes --- setup.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.ts b/setup.ts index a068cb2ab9..3c35fc69d3 100644 --- a/setup.ts +++ b/setup.ts @@ -1,8 +1,10 @@ +// eslint-disable-next-line import * as cryptolib from "crypto"; import dotenv from "dotenv"; import fs from "fs"; import inquirer from "inquirer"; import path from "path"; +/* eslint-disable */ import type { ExecException } from "child_process"; import { exec } from "child_process"; import { MongoClient } from "mongodb"; @@ -29,6 +31,7 @@ import { askForSuperAdminEmail } from "./src/setup/superAdmin"; import { updateEnvVariable } from "./src/setup/updateEnvVariable"; import { verifySmtpConnection } from "./src/setup/verifySmtpConnection"; import { loadDefaultOrganiation } from "./src/utilities/loadDefaultOrg"; +/* eslint-enable */ dotenv.config(); @@ -168,6 +171,7 @@ function transactionLogPath(logPath: string | null): void { async function askForTransactionLogPath(): Promise { let logPath: string | null; // Keep asking for path, until user gives a valid path + // eslint-disable-next-line no-constant-condition while (true) { const response = await inquirer.prompt([ { From 3b4e431859da94e5dc75ce7a543974554947abf2 Mon Sep 17 00:00:00 2001 From: Disha Date: Sun, 6 Oct 2024 17:26:00 +0530 Subject: [PATCH 50/50] reverted: unrelated changes --- setup.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.ts b/setup.ts index b9d18d23d9..3d31dd86ba 100644 --- a/setup.ts +++ b/setup.ts @@ -1,10 +1,8 @@ -// eslint-disable-next-line import * as cryptolib from "crypto"; import dotenv from "dotenv"; import fs from "fs"; import inquirer from "inquirer"; import path from "path"; -/* eslint-disable */ import type { ExecException } from "child_process"; import { exec } from "child_process"; import { MongoClient } from "mongodb"; @@ -34,7 +32,6 @@ import { loadDefaultOrganiation } from "./src/utilities/loadDefaultOrg"; import { isMinioInstalled } from "./src/setup/isMinioInstalled"; import { installMinio } from "./src/setup/installMinio"; - dotenv.config(); // Check if all the fields in .env.sample are present in .env