Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add mutations to mark chat messages as read, update message, update group chat info, add user to group chat, share images in chats, and create dedicated group chats for events #2625

Open
wants to merge 72 commits into
base: develop
Choose a base branch
from

Conversation

disha1202
Copy link

@disha1202 disha1202 commented Oct 29, 2024

What kind of change does this PR introduce?
Feature

Issue Number:

Fixes #2624

Did you add tests for your changes?
Yes

Snapshots/Videos:

If relevant, did you update the documentation?

Summary

Does this PR introduce a breaking change?

Other information

Have you read the contributing guide?

Summary by CodeRabbit

  • New Features

    • Enhanced chat functionality with new fields for tracking unseen messages and media in messages.
    • New mutations added for marking messages as read and adding users to group chats.
    • New queries for fetching group chats and unread chats by user ID.
    • Support for creating chats when creating events.
  • Bug Fixes

    • Improved error handling in various resolvers to ensure proper responses for unauthorized access and missing entities.
  • Documentation

    • Updated GraphQL schema definitions to reflect new input types and mutation signatures.
  • Tests

    • Comprehensive test coverage added for new and modified resolvers, ensuring functionality and error handling are validated.

Copy link

coderabbitai bot commented Oct 29, 2024

Walkthrough

The pull request introduces significant enhancements to the GraphQL schema and related functionality for chat operations. Key updates include the addition of new fields, input types, and mutations for managing chats and messages. Notably, the Chat and ChatMessage types are expanded, with new functionalities for marking messages as read, adding users to group chats, and sending messages with media. The event-related functions are updated to accommodate chat integration, improving the overall chat management capabilities within the application.

Changes

File Path Change Summary
schema.graphql Added fields unseenMessagesByUsers to Chat, media to ChatMessage. Introduced new input types ChatWhereInput, UpdateChatInput, UpdateChatMessageInput. Updated mutations: addUserToGroupChat, modified sendMessageToChat, added markChatMessagesAsRead. Updated queries: modified chatsByUserId, added getGroupChatsByUserId, getUnreadChatsByUserId.
src/helpers/event/createEventHelpers/createRecurringEvent.ts Updated createRecurringEvent to include a new parameter chat.
src/helpers/event/createEventHelpers/createRecurringEventInstancesDuringQuery.ts Added createChat property to currentInputData.
src/helpers/event/createEventHelpers/createSingleEvent.ts Updated createSingleEvent to include a new parameter chat.
src/helpers/event/updateEventHelpers/getEventData.ts Updated getEventData to include a new property chat.
src/models/Chat.ts Added image and unseenMessagesByUsers properties to InterfaceChat and updated chatSchema.
src/models/ChatMessage.ts Added media property to InterfaceChatMessage and updated chatMessageSchema.
src/models/Event.ts Added chat property to InterfaceEvent and updated event schema.
src/resolvers/Chat/admins.ts Changed database query from parent.users to parent.admins.
src/resolvers/Chat/messages.ts Updated messages resolver to include context and handle media URLs.
src/resolvers/Mutation/addUserToGroupChat.ts Introduced a mutation to add a user to a group chat with error handling.
src/resolvers/Mutation/createChat.ts Enhanced user validation and added unseen messages tracking.
src/resolvers/Mutation/createEvent.ts Integrated chat creation logic into event creation.
src/resolvers/Mutation/index.ts Added new mutations: markChatMessagesAsRead, addUserToGroupChat, updateChat, updateChatMessage.
src/resolvers/Mutation/markChatMessagesAsRead.ts Introduced a mutation to mark messages as read with error checks.
src/resolvers/Mutation/sendMessageToChat.ts Modified to handle media file uploads and update unseen messages logic.
src/resolvers/Mutation/updateChat.ts Introduced a mutation for updating chat entities.
src/resolvers/Mutation/updateChatMessage.ts Introduced a mutation for updating chat messages.
src/resolvers/Query/chatById.ts Updated to include context and handle image URLs for group chats.
src/resolvers/Query/chatsByUserId.ts Updated to include sorting and context handling.
src/resolvers/Query/getGroupChatsByUserId.ts New query to fetch group chats associated with a user.
src/resolvers/Query/getUnreadChatsByUserId.ts New query to fetch unread chats for a user.
src/resolvers/Query/helperFunctions/getWhere.ts Updated to include ChatWhereInput for filtering.
src/typeDefs/inputs.ts Added ChatWhereInput and updated EventInput to include createChat.
src/typeDefs/mutations.ts Updated sendMessageToChat, added new mutations.
src/typeDefs/queries.ts Updated chatsByUserId and added new queries.
src/typeDefs/types.ts Added unseenMessagesByUsers and media fields, new input types.
src/types/generatedGraphQLTypes.ts Added new types and updated existing ones.
tests/helpers/chat.ts Introduced new functions for creating chat instances.
tests/resolvers/Chat/messages.spec.ts Enhanced test coverage for messagesResolver.
tests/resolvers/Event/baseRecurringEvent.spec.ts Added createChat property to test cases.
tests/resolvers/Mutation/addUserToGroupChat.spec.ts Introduced tests for addUserToGroupChat mutation.
tests/resolvers/Mutation/createEvent.spec.ts Added createChat property to test cases.
tests/resolvers/Mutation/markChatMessagesAsRead.spec.ts Introduced tests for markChatMessagesAsRead mutation.
tests/resolvers/Mutation/sendMessageToChat.spec.ts Enhanced test setup for sendMessageToChat.
tests/resolvers/Mutation/updateChat.spec.ts Introduced tests for updateChat mutation.
tests/resolvers/Mutation/updateChatMessage.spec.ts Introduced tests for updateChatMessage mutation.
tests/resolvers/Query/chatById.spec.ts Enhanced test coverage for chatById.
tests/resolvers/Query/chatsByUserId.spec.ts Updated resolver invocation with context.
tests/resolvers/Query/getGroupChatsByUserId.spec.ts Introduced tests for getGroupChatsByUserId.
tests/resolvers/Query/getUnreadChatsByUserId.spec.ts Introduced tests for getUnreadChatsByUserId.
tests/resolvers/RecurrenceRule/baseRecurringEvent.spec.ts Added createChat property to test cases.
tests/resolvers/RecurrenceRule/organization.spec.ts Added createChat property to test cases.

Assessment against linked issues

Objective Addressed Explanation
Add mutations to mark chat messages as read (2624)
Add mutations to update message (2624)
Add mutations to update group chat info (2624)
Add mutations to add user to group chat (2624)
Share images in chats (2624)
Create dedicated group chats for events (2624)

Possibly related PRs

  • Updated chat schema #2466: This PR updates the chat schema by merging the DirectChat and GroupChat types into a unified Chat entity, which aligns with the changes made in the main PR regarding the enhancements to the Chat type and related functionalities.
  • feat: implemented Reply functionality for chat #2584: This PR implements reply functionality for chat messages, which is relevant to the main PR's modifications to the ChatMessage type, specifically the addition of the media field and the updates to the sendMessageToChat mutation that now accommodates media handling.

🐰 In the meadow, we chat and play,
New features bloom, brightening the day!
With messages read and media to share,
Group chats unite us, showing we care.
So hop along, let’s celebrate this cheer,
For every new update brings us near! 🌼✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented Oct 29, 2024

Our Pull Request Approval Process

Thanks for contributing!

Testing Your Code

Remember, your PRs won't be reviewed until these criteria are met:

  1. We don't merge PRs with poor code quality.
    1. Follow coding best practices such that CodeRabbit.ai approves your PR.
  2. We don't merge PRs with failed tests.
    1. When tests fail, click on the Details link to learn more.
    2. Write sufficient tests for your changes (CodeCov Patch Test). Your testing level must be better than the target threshold of the repository
    3. Tests may fail if you edit sensitive files. Ask to add the ignore-sensitive-files-pr label if the edits are necessary.
  3. We cannot merge PRs with conflicting files. These must be fixed.

Our policies make our code better.

Reviewers

Do not assign reviewers. Our Queue Monitors will review your PR and assign them.
When your PR has been assigned reviewers contact them to get your code reviewed and approved via:

  1. comments in this PR or
  2. our slack channel

Reviewing Your Code

Your reviewer(s) will have the following roles:

  1. arbitrators of future discussions with other contributors about the validity of your changes
  2. point of contact for evaluating the validity of your work
  3. person who verifies matching issues by others that should be closed.
  4. person who gives general guidance in fixing your tests

CONTRIBUTING.md

Read our CONTRIBUTING.md file. Most importantly:

  1. PRs with issues not assigned to you will be closed by the reviewer
  2. Fix the first comment in the PR so that each issue listed automatically closes

Other

  1. 🎯 Please be considerate of our volunteers' time. Contacting the person who assigned the reviewers is not advised unless they ask for your input. Do not @ the person who did the assignment otherwise.
  2. Read the CONTRIBUTING.md file make

Copy link

codecov bot commented Oct 29, 2024

Codecov Report

Attention: Patch coverage is 93.88235% with 26 lines in your changes missing coverage. Please review.

Project coverage is 98.39%. Comparing base (42024f6) to head (ac4256c).
Report is 31 commits behind head on develop.

Files with missing lines Patch % Lines
src/resolvers/Mutation/sendMessageToChat.ts 62.50% 9 Missing ⚠️
src/resolvers/Mutation/registerForEvent.ts 0.00% 7 Missing ⚠️
src/resolvers/Mutation/createChat.ts 78.57% 2 Missing and 1 partial ⚠️
src/resolvers/Chat/messages.ts 84.61% 2 Missing ⚠️
src/resolvers/Query/chatsByUserId.ts 85.71% 2 Missing ⚠️
...pers/event/createEventHelpers/createSingleEvent.ts 50.00% 1 Missing ⚠️
...c/helpers/event/updateEventHelpers/getEventData.ts 50.00% 1 Missing ⚠️
src/resolvers/Mutation/createEvent.ts 94.44% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2625      +/-   ##
===========================================
- Coverage    98.44%   98.39%   -0.05%     
===========================================
  Files          342      348       +6     
  Lines        16734    17150     +416     
  Branches      2408     2481      +73     
===========================================
+ Hits         16473    16874     +401     
- Misses         258      272      +14     
- Partials         3        4       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (80)
src/resolvers/Chat/messages.ts (1)

13-17: 🛠️ Refactor suggestion

Consider preserving message order.

The current query might return messages in a different order than specified in parent.messages. This could affect message chronology in the chat interface.

Consider maintaining the original order using MongoDB's $lookup aggregation or post-query sorting:

-  let messages = await ChatMessage.find({
-    _id: {
-      $in: parent.messages,
-    },
-  }).lean();
+  let messages = await ChatMessage.aggregate([
+    {
+      $match: {
+        _id: { $in: parent.messages.map(id => new ObjectId(id)) }
+      }
+    },
+    {
+      $addFields: {
+        __order: {
+          $indexOfArray: [parent.messages.map(id => id.toString()), { $toString: "$_id" }]
+        }
+      }
+    },
+    { $sort: { "__order": 1 } },
+    { $project: { "__order": 0 } }
+  ]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  let messages = await ChatMessage.aggregate([
    {
      $match: {
        _id: { $in: parent.messages.map(id => new ObjectId(id)) }
      }
    },
    {
      $addFields: {
        __order: {
          $indexOfArray: [parent.messages.map(id => id.toString()), { $toString: "$_id" }]
        }
      }
    },
    { $sort: { "__order": 1 } },
    { $project: { "__order": 0 } }
  ]);
src/resolvers/Query/chatsByUserId.ts (2)

14-16: ⚠️ Potential issue

Add error handling for missing context.apiRootUrl

The resolver now depends on context.apiRootUrl for group chat images, but there's no validation to ensure it exists.

Add validation at the start of the function:

export const chatsByUserId: QueryResolvers["chatsByUserId"] = async (
  _parent,
  args,
  context,
) => {
+ if (!context.apiRootUrl) {
+   throw new Error('API root URL is not configured');
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  _parent,
  args,
  context,
) => {
  if (!context.apiRootUrl) {
    throw new Error('API root URL is not configured');
  }

18-25: 🛠️ Refactor suggestion

Consider making sort configurable via query arguments

The sort is currently hardcoded to updatedAt: -1. Consider making it configurable through GraphQL arguments for better flexibility.

Example implementation:

+ type SortInput {
+   field: String
+   order: SortOrder
+ }

  const sort = {
-   updatedAt: -1,
+   [args.sort?.field || 'updatedAt']: args.sort?.order || -1,
  } as

Committable suggestion was skipped due to low confidence.

src/resolvers/Query/getGroupChatsByUserId.ts (5)

15-22: 🛠️ Refactor suggestion

Simplify sort configuration type.

The complex type assertion for the sort configuration can be simplified using a more specific type.

-    const sort = {
-      updatedAt: -1,
-    } as
-      | string
-      | { [key: string]: SortOrder | { $meta: unknown } }
-      | [string, SortOrder][]
-      | null
-      | undefined;
+    const sort: { [key: string]: SortOrder } = {
+      updatedAt: -1
+    };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const sort: { [key: string]: SortOrder } = {
      updatedAt: -1
    };

24-28: ⚠️ Potential issue

Add user context validation.

The resolver assumes context.userId exists but doesn't validate it. This could lead to unexpected behavior if the context is invalid.

Add validation before the database query:

+    if (!context.userId) {
+      throw new Error('User must be authenticated');
+    }
+
     const chats = await Chat.find({
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    if (!context.userId) {
      throw new Error('User must be authenticated');
    }

    const chats = await Chat.find({
      users: context.userId,
      isGroup: true,
    })
      .sort(sort)

31-36: ⚠️ Potential issue

Secure image URL construction.

The current image URL construction could be vulnerable to path traversal attacks. Additionally, there's no validation of the image path format.

Add path validation and sanitization:

     const chatList = chats.map((chat) => {
       if (chat.isGroup && chat.image) {
+        // Ensure image path is relative and contains no path traversal
+        const sanitizedImage = chat.image.replace(/^\/+/, '').replace(/\.\./g, '');
-        return { ...chat, image: `${context.apiRootUrl}${chat.image}` };
+        return { ...chat, image: `${context.apiRootUrl}/${sanitizedImage}` };
       }
       return chat;
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const chatList = chats.map((chat) => {
      if (chat.isGroup && chat.image) {
        // Ensure image path is relative and contains no path traversal
        const sanitizedImage = chat.image.replace(/^\/+/, '').replace(/\.\./g, '');
        return { ...chat, image: `${context.apiRootUrl}/${sanitizedImage}` };
      }
      return chat;
    });

4-12: ⚠️ Potential issue

Update documentation to match implementation.

The documentation has several inconsistencies:

  1. It mentions throwing NotFoundError but this isn't implemented
  2. References "directChats" but this resolver returns group chats
  3. The @param _parent has a dangling hyphen

Apply this diff to fix the documentation:

 /**
- * This query will fetch all the Chats for the current user from the database.
+ * This query will fetch all group 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.
+ * @returns An array of group chat objects that the current user is a member of.
+ * Returns an empty array if no group chats are found.
  * @remarks You can learn about GraphQL `Resolvers`
  * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}.
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

/**
 * This query will fetch all group chats for the current user from the database.
 * @param _parent-
 * @param args - An object that contains `id` of the user.
 * @returns An array of group chat objects that the current user is a member of.
 * Returns an empty array if no group chats are found.
 * @remarks You can learn about GraphQL `Resolvers`
 * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}.
 */

24-29: 🛠️ Refactor suggestion

Add pagination and error handling.

Consider these improvements for scalability and reliability:

  1. Implement pagination to handle large datasets efficiently
  2. Add error handling for the database operation
+    try {
+      const limit = 20; // or get from args
+      const skip = 0;   // or get from args
+
       const chats = await Chat.find({
         users: context.userId,
         isGroup: true,
       })
         .sort(sort)
+        .limit(limit)
+        .skip(skip)
         .lean();
+    } catch (error) {
+      throw new Error(`Failed to fetch group chats: ${error.message}`);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    try {
      const limit = 20; // or get from args
      const skip = 0;   // or get from args

      const chats = await Chat.find({
        users: context.userId,
        isGroup: true,
      })
        .sort(sort)
        .limit(limit)
        .skip(skip)
        .lean();
    } catch (error) {
      throw new Error(`Failed to fetch group chats: ${error.message}`);
    }
src/resolvers/Query/getUnreadChatsByUserId.ts (1)

15-22: 🛠️ Refactor suggestion

Simplify sort configuration using mongoose constants.

The sort configuration can be improved for better maintainability and type safety.

Apply this diff to simplify the sort configuration:

+import { SortOrder } from "mongoose";
+
+const CHAT_SORT_CONFIG = {
+  updatedAt: SortOrder.DESC,
+} as const;
+
 export const getUnreadChatsByUserId: QueryResolvers["getUnreadChatsByUserId"] =
   async (_parent, _args, context) => {
-    const sort = {
-      updatedAt: -1,
-    } as
-      | string
-      | { [key: string]: SortOrder | { $meta: unknown } }
-      | [string, SortOrder][]
-      | null
-      | undefined;
+    const sort = CHAT_SORT_CONFIG;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

import { SortOrder } from "mongoose";

const CHAT_SORT_CONFIG = {
  updatedAt: SortOrder.DESC,
} as const;

    const sort = CHAT_SORT_CONFIG;
tests/resolvers/Chat/messages.spec.ts (2)

18-18: ⚠️ Potential issue

Add validation for array access.

Direct array index access could fail if userOrgChat doesn't have enough elements.

Consider adding validation:

-  testMessage = userOrgChat[3];
+  if (userOrgChat.length < 4) {
+    throw new Error("Test chat messages not properly initialized");
+  }
+  testMessage = userOrgChat[3];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  if (userOrgChat.length < 4) {
    throw new Error("Test chat messages not properly initialized");
  }
  testMessage = userOrgChat[3];

47-66: 🛠️ Refactor suggestion

Optimize query and improve test description.

The test case has a few areas for improvement:

  1. Using $in operator for a single ID is inefficient
  2. Test description could be more specific about what's being tested

Consider these improvements:

-  it(`returns message`, async () => {
+  it(`returns specific message when filtered by message ID`, async () => {
     const parent = testChat?.toObject();
     if (!parent) {
       throw new Error("Parent object is undefined.");
     }

     const messagesPayload = await messagesResolver?.(
       parent,
       {},
-      { apiRootUrl: "" },
+      { apiRootUrl: "https://api.example.com" },
     );

     const messages = await ChatMessage.find({
-      _id: {
-        $in: testMessage?._id,
-      },
+      _id: testMessage?._id,
     }).lean();

     expect(messagesPayload).toEqual(messages);
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  it(`returns specific message when filtered by message ID`, async () => {
    const parent = testChat?.toObject();
    if (!parent) {
      throw new Error("Parent object is undefined.");
    }

    const messagesPayload = await messagesResolver?.(
      parent,
      {},
      { apiRootUrl: "https://api.example.com" },
    );

    const messages = await ChatMessage.find({
      _id: testMessage?._id,
    }).lean();

    expect(messagesPayload).toEqual(messages);
  });
tests/resolvers/Event/baseRecurringEvent.spec.ts (1)

56-56: 💡 Codebase verification

Based on the gathered evidence, I can now provide the final response:

Test coverage for chat creation is needed in the main event creation tests

The chat creation functionality is implemented in the codebase (createEvent.ts and createChat.ts), but there's no test coverage for the positive case (createChat: true) in any of the event test files. This is particularly important since:

  • The implementation shows chat creation logic is triggered when createChat is true
  • The feature affects both regular and recurring events
  • The helper code in getEventData.ts shows chat-related state management

Please add test coverage in tests/resolvers/Mutation/createEvent.spec.ts to verify:

  • Chat creation when createChat: true
  • Chat association with the event
  • Chat properties (name derived from event title)
🔗 Analysis chain

Add test coverage for chat creation.

While the test covers the case where createChat is false, we should also add test coverage for when createChat is true to ensure the chat creation functionality works correctly with recurring events.

Let's verify if other event test files have complete coverage:

Consider adding another test case with this structure:

it('creates a chat when createChat is true', async () => {
  const args: MutationCreateEventArgs = {
    data: {
      // ... existing test data ...
      createChat: true,
    },
    // ... rest of the test setup ...
  };
  
  // Add assertions to verify:
  // 1. Chat is created and associated with the event
  // 2. Base recurring event relationship with chat is correct
});

Let me gather more context about the chat-related functionality in events to ensure our verification is thorough.


Let me check the event creation test files to see if there are any existing test cases for chat creation in other event types.


Let me check the main event creation test file for chat-related test coverage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check test coverage for createChat in event-related tests
# Expected: Both true/false cases should be tested across event test files

# Search for createChat in event test files
rg -A 5 "createChat:" "tests/resolvers/Event/"

Length of output: 985


Script:

#!/bin/bash
# Check for chat-related event tests and implementations
# Look for chat creation patterns in test files and source code

# Search for chat-related test cases in event tests
rg -B 2 -A 5 "it\(.*chat" "tests/resolvers/Event/"

# Search for chat creation implementation in resolvers
ast-grep --pattern 'createChat: boolean'

# Look for chat creation logic
rg -B 2 -A 5 "createChat.*=.*" "src/"

Length of output: 1067


Script:

#!/bin/bash
# Check event creation test files for chat-related test coverage

# Search for test files related to event creation
fd ".*event.*spec.ts$" tests/resolvers/

# Look for existing chat-related test cases in these files
rg -B 3 -A 7 "it\(.*create.*event" tests/resolvers/

Length of output: 12646


Script:

#!/bin/bash
# Check createEvent.spec.ts for chat-related test data

# Look for createChat in the main event creation test file
rg -B 5 -A 10 "data: {" "tests/resolvers/Mutation/createEvent.spec.ts"

# Also check the implementation to see what happens when createChat is true
rg -B 5 -A 10 "createChat.*true" "src/"

Length of output: 1016

tests/resolvers/RecurrenceRule/organization.spec.ts (1)

57-57: 🛠️ Refactor suggestion

Consider adding test cases for chat creation scenarios.

While the test verifies the organization resolver functionality, it would be beneficial to add test cases that explicitly verify:

  1. A chat is actually created when createChat is true
  2. No chat is created when createChat is false
  3. Error handling for chat creation failures

Here's a suggested test structure:

describe("event chat creation", () => {
  it("creates a chat when createChat is true", async () => {
    // ... existing test setup ...
    const createEventPayload = await createEventResolver?.({}, args, context);
    
    // Verify chat was created and linked to the event
    const chat = await Chat.findOne({ eventId: createEventPayload?.id });
    expect(chat).toBeTruthy();
  });

  it("does not create a chat when createChat is false", async () => {
    const argsWithoutChat = {
      ...args,
      data: { ...args.data, createChat: false }
    };
    const createEventPayload = await createEventResolver?.({}, argsWithoutChat, context);
    
    // Verify no chat was created
    const chat = await Chat.findOne({ eventId: createEventPayload?.id });
    expect(chat).toBeNull();
  });
});
src/resolvers/Mutation/createChat.ts (1)

61-66: ⚠️ Potential issue

Add error handling and file size validation for image uploads.

The image upload implementation needs additional safeguards:

  1. Missing test coverage as indicated by codecov
  2. No file size validation
  3. No error handling for failed uploads

Consider adding these safety checks:

   let uploadMediaFile = null;

   if (args.data.isGroup && args.data.image) {
+    // Validate image size (e.g., 5MB limit)
+    const base64Size = Buffer.from(args.data.image.split(',')[1], 'base64').length;
+    if (base64Size > 5 * 1024 * 1024) {
+      throw new errors.ValidationError(
+        'Image size exceeds limit',
+        'IMAGE_SIZE_EXCEEDED'
+      );
+    }
+    
+    try {
       uploadMediaFile = await uploadEncodedImage(args.data.image);
+    } catch (error) {
+      throw new errors.ValidationError(
+        'Failed to upload image',
+        'IMAGE_UPLOAD_FAILED'
+      );
+    }
     args.data.image = uploadMediaFile;
   }

Would you like me to help generate test cases for the image upload functionality?

Committable suggestion was skipped due to low confidence.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 64-65: src/resolvers/Mutation/createChat.ts#L64-L65
Added lines #L64 - L65 were not covered by tests

tests/resolvers/Query/getUnreadChatsByUserId.spec.ts (3)

58-63: 🛠️ Refactor suggestion

Refactor duplicated filtering logic.

The chat filtering logic is duplicated. Consider extracting it into a helper function.

+const filterUnreadChats = (chats: any[], userId: string) => {
+  return chats.filter((chat) => {
+    const unseenMessages = JSON.parse(
+      chat.unseenMessagesByUsers as unknown as string,
+    );
+    return unseenMessages[userId] > 0;
+  });
+};

-    const filteredChats = chatsByUserId.filter((chat) => {
-      const unseenMessages = JSON.parse(
-        chat.unseenMessagesByUsers as unknown as string,
-      );
-      return unseenMessages[testUser?._id] > 0;
-    });
+    const filteredChats = filterUnreadChats(chatsByUserId, testUser?._id);

Also applies to: 83-88


59-61: ⚠️ Potential issue

Add error handling for JSON.parse.

The JSON.parse operation could throw if the data is malformed. Consider adding error handling or validation.

-      const unseenMessages = JSON.parse(
-        chat.unseenMessagesByUsers as unknown as string,
-      );
+      let unseenMessages = {};
+      try {
+        unseenMessages = JSON.parse(
+          chat.unseenMessagesByUsers as unknown as string,
+        );
+      } catch (error) {
+        console.error('Invalid unseenMessagesByUsers format:', error);
+        return false;
+      }

Also applies to: 84-86


29-41: ⚠️ Potential issue

Improve error test case reliability.

The current error test doesn't guarantee that an error is actually thrown. Use expect().rejects.toThrow() for better assertions.

-    try {
-      const args: QueryChatsByUserIdArgs = {
-        id: new Types.ObjectId().toString(),
-      };
-
-      await getUnreadChatsByUserIdResolver?.({}, args, {});
-    } catch (error: unknown) {
-      expect((error as Error).message).toEqual("Chats not found");
-    }
+    const args: QueryChatsByUserIdArgs = {
+      id: new Types.ObjectId().toString(),
+    };
+
+    await expect(
+      getUnreadChatsByUserIdResolver?.({}, args, {})
+    ).rejects.toThrow("Chats not found");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

describe("resolvers -> Query -> getUnreadChatsByUserId", () => {
  it(`throws NotFoundError if no Chats exists with chats.users
  containing user with _id === args.id`, async () => {
    const args: QueryChatsByUserIdArgs = {
      id: new Types.ObjectId().toString(),
    };

    await expect(
      getUnreadChatsByUserIdResolver?.({}, args, {})
    ).rejects.toThrow("Chats not found");
  });
tests/resolvers/Query/getGroupChatsByUserId.spec.ts (4)

58-70: 🛠️ Refactor suggestion

Extract common filter logic to reduce duplication.

The chat filtering logic is duplicated between test cases. Consider extracting it to a helper function:

const getFilteredChats = async (userId: string) => {
  const chats = await Chat.find({ users: userId }).lean();
  return chats.filter((chat) => {
    const unseenMessages = JSON.parse(
      chat.unseenMessagesByUsers as unknown as string
    );
    return unseenMessages[userId] > 0;
  });
};

Then use it in both test cases:

-    const chatsByUserId = await Chat.find({
-      users: testUser?._id,
-    }).lean();
-
-    const filteredChats = chatsByUserId.filter((chat) => {
-      const unseenMessages = JSON.parse(
-        chat.unseenMessagesByUsers as unknown as string,
-      );
-      return unseenMessages[testUser?._id] > 0;
-    });
+    const filteredChats = await getFilteredChats(testUser._id);

Also applies to: 83-95


63-65: ⚠️ Potential issue

Improve type safety for unseenMessagesByUsers parsing.

The current type casting of unseenMessagesByUsers is unsafe. Consider adding type validation:

interface UnseenMessages {
  [userId: string]: number;
}

function parseUnseenMessages(raw: unknown): UnseenMessages {
  if (typeof raw !== 'string') {
    throw new Error('unseenMessagesByUsers must be a string');
  }
  const parsed = JSON.parse(raw);
  if (typeof parsed !== 'object' || parsed === null) {
    throw new Error('Invalid unseenMessagesByUsers format');
  }
  return parsed as UnseenMessages;
}

Then use it in the filter function:

-      const unseenMessages = JSON.parse(
-        chat.unseenMessagesByUsers as unknown as string,
-      );
+      const unseenMessages = parseUnseenMessages(chat.unseenMessagesByUsers);

Also applies to: 88-90


20-31: ⚠️ Potential issue

Add error handling and improve type safety in test setup.

The test setup could be more robust with the following improvements:

  1. Add error handling for database connection:
 beforeAll(async () => {
-  MONGOOSE_INSTANCE = await connect();
+  try {
+    MONGOOSE_INSTANCE = await connect();
+  } catch (error) {
+    console.error('Failed to connect to test database:', error);
+    throw error;
+  }
   const resultArray = await createTestChat();
  1. Add type assertion for better type safety:
-  const resultArray = await createTestChat();
+  const resultArray = (await createTestChat()) as TestUserType[];
  1. Clean up unused destructuring:
-  [testUser1, ,] = await createTestGroupChatWithoutImage();
+  [testUser1] = await createTestGroupChatWithoutImage();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

beforeAll(async () => {
  try {
    MONGOOSE_INSTANCE = await connect();
  } catch (error) {
    console.error('Failed to connect to test database:', error);
    throw error;
  }
  const resultArray = (await createTestChat()) as TestUserType[];

  [testUser1] = await createTestGroupChatWithoutImage();

  testUser = resultArray[0];
});

afterAll(async () => {
  await disconnect(MONGOOSE_INSTANCE);
});

33-70: ⚠️ Potential issue

Improve type safety and reduce code duplication in tests.

The first two test cases need improvements in error handling and type safety:

  1. Extract error message to a constant:
+const CHATS_NOT_FOUND_ERROR = "Chats not found";
+
 describe("resolvers -> Query -> getGroupChatsByUserId", () => {
   it(`throws NotFoundError if no Chats exists with chats.users
   containing user with _id === args.id`, async () => {
     try {
       const args: QueryChatsByUserIdArgs = {
         id: new Types.ObjectId().toString(),
       };

       await getGroupChatsByUserIdResolver?.({}, args, {});
+      fail('Expected error to be thrown');
     } catch (error: unknown) {
-      expect((error as Error).message).toEqual("Chats not found");
+      expect((error as Error).message).toEqual(CHATS_NOT_FOUND_ERROR);
     }
   });
  1. Remove optional chaining on resolver as it should always be defined:
-    await getGroupChatsByUserIdResolver?.({}, args, {});
+    await getGroupChatsByUserIdResolver({}, args, {});

Committable suggestion was skipped due to low confidence.

src/models/ChatMessage.ts (1)

16-16: 🛠️ Refactor suggestion

Consider using a more specific type for media content.

The media field type could be more descriptive and constrained. Consider using a union type or interface that explicitly defines the expected media format (e.g., URL, base64, file path).

-  media: string;
+  media: {
+    url: string;
+    type: 'IMAGE' | 'VIDEO' | 'FILE';
+    mimeType: string;
+  };

Also, please add JSDoc documentation for this new field to maintain consistency with the rest of the interface.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  media: {
    url: string;
    type: 'IMAGE' | 'VIDEO' | 'FILE';
    mimeType: string;
  };
src/models/Chat.ts (2)

14-14: 🛠️ Refactor suggestion

Consider using a more specific type for unseenMessagesByUsers

Using the raw JSON type reduces type safety. Consider defining a specific interface that represents the structure of unseen messages data.

-  unseenMessagesByUsers: JSON;
+  unseenMessagesByUsers: {
+    [userId: string]: {
+      count: number;
+      lastSeen?: Date;
+    };
+  };

Also, please add JSDoc comments for these new fields to maintain documentation consistency.

Also applies to: 24-24


103-106: 🛠️ Refactor suggestion

Improve schema definition for unseenMessagesByUsers

Using the JSON type in Mongoose has limitations:

  1. Limited query capabilities on nested properties
  2. No schema validation for the structure
  3. Missing default value for a required field

Consider using a nested schema structure:

-    unseenMessagesByUsers: {
-      type: JSON,
-      required: true,
-    },
+    unseenMessagesByUsers: {
+      type: Map,
+      of: new Schema({
+        count: { type: Number, required: true, default: 0 },
+        lastSeen: { type: Date }
+      }),
+      required: true,
+      default: new Map()
+    },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    unseenMessagesByUsers: {
      type: Map,
      of: new Schema({
        count: { type: Number, required: true, default: 0 },
        lastSeen: { type: Date }
      }),
      required: true,
      default: new Map()
    },
src/typeDefs/queries.ts (2)

51-52: ⚠️ Potential issue

Add user ID parameter for security.

The query getUnreadChatsByUserId should require a user ID parameter to prevent unauthorized access to other users' unread chats.

Apply this diff to fix the security issue:

-    getUnreadChatsByUserId: [Chat]
+    getUnreadChatsByUserId(userId: ID!): [Chat]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    getUnreadChatsByUserId(userId: ID!): [Chat]


53-53: ⚠️ Potential issue

Add user ID parameter for security.

The query getGroupChatsByUserId should require a user ID parameter to prevent unauthorized access to other users' group chats.

Apply this diff to fix the security issue:

-    getGroupChatsByUserId: [Chat]
+    getGroupChatsByUserId(userId: ID!): [Chat]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    getGroupChatsByUserId(userId: ID!): [Chat]
tests/resolvers/Mutation/markChatMessagesAsRead.spec.ts (5)

47-116: 🛠️ Refactor suggestion

Refactor repeated spy mocking pattern.

The translation spy mocking pattern is repeated in multiple tests. Consider extracting it into a helper function or beforeEach hook.

let translateSpy: SpyInstance;

beforeEach(() => {
  const { requestContext } = require("../../../src/libraries");
  translateSpy = vi
    .spyOn(requestContext, "translate")
    .mockImplementation((message) => message);
});

afterEach(() => {
  translateSpy.mockRestore();
});

64-66: 🛠️ Refactor suggestion

Enhance error assertions with type checking.

The error assertions only check the error message. Consider also verifying the error type for more robust testing.

-expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE);
+expect(error).toBeInstanceOf(Error);
+expect(error).toHaveProperty('message', USER_NOT_FOUND_ERROR.MESSAGE);
+expect(error).toHaveProperty('code', USER_NOT_FOUND_ERROR.CODE);

Also applies to: 88-89, 111-113


41-41: ⚠️ Potential issue

Fix typo in describe block name.

The describe block has a typo: "markChatMessagesMessagesAsRead" should be "markChatMessagesAsRead".

-describe("resolvers -> Mutation -> markChatMessagesMessagesAsRead", () => {
+describe("resolvers -> Mutation -> markChatMessagesAsRead", () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

describe("resolvers -> Mutation -> markChatMessagesAsRead", () => {

27-35: 🛠️ Refactor suggestion

Consider moving test data creation into individual tests.

The test data setup in beforeAll creates shared state across all tests. For better test isolation and to prevent potential interference between tests, consider moving the test data creation into the individual test cases where they are needed.

-let testUser: TestUserType;
-let testChat: TestChatType;
-beforeAll(async () => {
-  MONGOOSE_INSTANCE = await connect();
-  const resultsArray = await createTestUserAndOrganization();
-  testUser = resultsArray[0];
-  [, , testChat] = await createTestChatMessage();
-});
+beforeAll(async () => {
+  MONGOOSE_INSTANCE = await connect();
+});

Committable suggestion was skipped due to low confidence.


118-130: ⚠️ Potential issue

Add assertions to verify successful mutation result.

The successful test case doesn't verify that the messages were actually marked as read. Consider adding assertions to check the return value and database state.

 await markChatMessagesAsReadResolver?.({}, args, context);
+const result = await markChatMessagesAsReadResolver?.({}, args, context);
+expect(result).toBeTruthy();
+
+// Verify database state
+const updatedChat = await Chat.findById(args.chatId);
+expect(updatedChat.messages.every(msg => msg.readBy.includes(args.userId))).toBe(true);

Committable suggestion was skipped due to low confidence.

tests/resolvers/Mutation/updateChat.spec.ts (3)

51-75: 🛠️ Refactor suggestion

Standardize spy cleanup and enhance test coverage.

Several improvements needed across multiple test cases:

  1. Some tests are missing spy cleanup (e.g., successful update test)
  2. The successful update test could verify more fields
  3. Error assertions could use expect.toThrow() pattern for better error handling

Example improvement for the successful update test:

    const updatedChat = await updateChatResolver?.({}, args, context);
    expect(updatedChat?.name).toEqual(args.input.name);
+   expect(updatedChat?._id).toEqual(args.input._id);
+   expect(updatedChat?.users).toBeDefined();
+   expect(updatedChat?.users).toContain(context.userId);

Example improvement for error assertions:

-   try {
-     await updateChatResolver?.({}, args, context);
-   } catch (error: unknown) {
-     expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE);
-   }
+   await expect(
+     updateChatResolver?.({}, args, context)
+   ).rejects.toThrow(USER_NOT_FOUND_ERROR.MESSAGE);

Also applies to: 77-101, 130-145


45-45: ⚠️ Potential issue

Fix incorrect describe block name.

The describe block is named "addUserToGroupChat" but this test file is for the "updateChat" mutation.

-describe("resolvers -> Mutation -> addUserToGroupChat", () => {
+describe("resolvers -> Mutation -> updateChat", () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

describe("resolvers -> Mutation -> updateChat", () => {

147-170: ⚠️ Potential issue

Enhance image upload test assertions.

The test for updating chat with image doesn't verify that the image URL was actually updated in the chat. Consider adding assertions to check the final state of the chat.

    const updatedChat = await updateChatResolver?.({}, args, context);
+   expect(updatedChat?.image).toEqual(args.input.image);
    spy.mockRestore();

Committable suggestion was skipped due to low confidence.

tests/helpers/chat.ts (3)

134-134: 🛠️ Refactor suggestion

Consider parameterizing the media field.

The hardcoded "media" value might not be suitable for all test scenarios.

-        media: "media",
+        media: mediaContent ?? "default-media",

Committable suggestion was skipped due to low confidence.


138-149: 🛠️ Refactor suggestion

Optimize database operations by combining update and fetch.

The separate update and fetch operations can be combined using { new: true } option.

-      await Chat.findByIdAndUpdate(
+      const chat = await Chat.findByIdAndUpdate(
         {
           _id: testChat._id,
         },
         {
           messages: [testChatMessage._id],
         },
+        { new: true }
       );
-
-      const chat = await Chat.findById(testChat._id);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      const chat = await Chat.findByIdAndUpdate(
        {
          _id: testChat._id,
        },
        {
          messages: [testChatMessage._id],
        },
        { new: true }
      );

      return [testUser, testOrganization, chat, testChatMessage];

31-33: 🛠️ Refactor suggestion

Consider parameterizing the unseen messages count.

The hardcoded value of 5 for unseenMessagesByUsers might not be flexible enough for different test scenarios.

-      unseenMessagesByUsers: JSON.stringify({
-        [testUser._id]: 5,
-      }),
+      unseenMessagesByUsers: JSON.stringify({
+        [testUser._id]: unseenMessagesCount ?? 5,
+      }),

Committable suggestion was skipped due to low confidence.

tests/resolvers/Mutation/addUserToGroupChat.spec.ts (1)

48-69: 🛠️ Refactor suggestion

Enhance error test cases for better reliability.

Consider the following improvements for error test cases:

  1. Move spy cleanup to afterEach to avoid repetition
  2. Add expect.assertions() to ensure errors are actually thrown
  3. Use more specific error type checking
 describe("resolvers -> Mutation -> addUserToGroupChat", () => {
   afterEach(() => {
     vi.doUnmock("../../../src/constants");
     vi.resetModules();
+    spy.mockRestore();
   });

   it(`throws NotFoundError message if current user does not exists`, async () => {
+    expect.assertions(1);
     // ... existing code ...
-    spy.mockRestore();
   });

Also applies to: 71-92, 94-117, 119-142, 144-165

src/resolvers/Mutation/createEvent.ts (1)

181-197: ⚠️ Potential issue

Add error handling for chat creation

The chat creation block needs additional error handling and validation:

  1. The chat creation could fail silently if the function is undefined
  2. There's no explicit error handling for chat creation failures
  3. The result of chat creation isn't validated before use

Consider wrapping the chat creation in a try-catch block and validating the result:

  let chat;

  if (args.data.createChat && typeof createChat === "function") {
+   try {
      chat = await createChat(
        _parent,
        {
          data: {
            name: args.data.title,
            organizationId: args.data.organizationId,
            userIds: [currentUser._id.toString()],
            isGroup: true,
-           image: null,
          },
        },
        context,
      );
+     if (!chat?._id) {
+       throw new Error("Chat creation failed: Invalid chat object returned");
+     }
+   } catch (error) {
+     throw new errors.ValidationError(
+       `Failed to create chat for event: ${error.message}`,
+       "CHAT_CREATION_FAILED"
+     );
+   }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  let chat;

  if (args.data.createChat && typeof createChat === "function") {
    try {
      chat = await createChat(
        _parent,
        {
          data: {
            name: args.data.title,
            organizationId: args.data.organizationId,
            userIds: [currentUser._id.toString()],
            isGroup: true,
          },
        },
        context,
      );
      if (!chat?._id) {
        throw new Error("Chat creation failed: Invalid chat object returned");
      }
    } catch (error) {
      throw new errors.ValidationError(
        `Failed to create chat for event: ${error.message}`,
        "CHAT_CREATION_FAILED"
      );
    }
  }
tests/resolvers/Mutation/updateChatMessage.spec.ts (3)

51-226: 🛠️ Refactor suggestion

Refactor common test setup to reduce duplication.

The test file has significant duplication in setup code. Consider extracting common setup into helper functions or beforeEach hooks.

Here's a suggested refactoring:

describe("resolvers -> Mutation -> updateChatMessage", () => {
  let requestContext: any;
  let spy: any;
  let updateChatMessageResolver: any;
  
  beforeEach(async () => {
    // Import dependencies
    const imports = await import("../../../src/libraries");
    requestContext = imports.requestContext;
    spy = vi
      .spyOn(requestContext, "translate")
      .mockImplementation((message) => message);
    
    const resolverImport = await import(
      "../../../src/resolvers/Mutation/updateChatMessage"
    );
    updateChatMessageResolver = resolverImport.updateChatMessage;
  });

  afterEach(() => {
    spy.mockRestore();
    vi.doUnmock("../../../src/constants");
    vi.resetModules();
  });

  const createTestArgs = (
    messageContent: string = "New Message",
    chatId: string = testChat?.id,
    messageId: string = testMessage?._id.toString() || ""
  ): MutationUpdateChatMessageArgs => ({
    input: { messageContent, chatId, messageId }
  });

  // Then each test becomes more concise:
  it(`throws NotFoundError message if current user does not exists`, async () => {
    const args = createTestArgs();
    const context = { userId: new Types.ObjectId().toString() };

    await expect(
      updateChatMessageResolver?.({}, args, context)
    ).rejects.toThrow(USER_NOT_FOUND_ERROR.MESSAGE);
  });
  
  // ... other tests follow similar pattern
});

45-45: ⚠️ Potential issue

Fix incorrect test suite name.

The describe block name "addUserToGroupChat" doesn't match the functionality being tested. This file tests the "updateChatMessage" mutation.

-describe("resolvers -> Mutation -> addUserToGroupChat", () => {
+describe("resolvers -> Mutation -> updateChatMessage", () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

describe("resolvers -> Mutation -> updateChatMessage", () => {

198-225: ⚠️ Potential issue

Complete the successful update test case.

The test case for successful message update is incomplete:

  1. Missing assertions to verify the updated message content
  2. Contains a debug console.log statement
  3. Doesn't verify the message was actually updated in the database

Here's how to improve the test:

 it(`updates the chat message and returns it`, async () => {
   const { requestContext } = await import("../../../src/libraries");
   const spy = vi
     .spyOn(requestContext, "translate")
     .mockImplementationOnce((message) => message);

   const newMessageContent = "New Message";
   const args: MutationUpdateChatMessageArgs = {
     input: {
-      messageContent: "New Message",
+      messageContent: newMessageContent,
       chatId: testChat?.id,
       messageId: testMessage?._id.toString()
         ? testMessage?._id.toString()
         : "",
     },
   };
   const context = {
     userId: testMessage?.sender,
   };
   const { updateChatMessage: updateChatMessageResolver } = await import(
     "../../../src/resolvers/Mutation/updateChatMessage"
   );

   const updatedMessage = await updateChatMessageResolver?.({}, args, context);

-  console.log(updatedMessage);
+  // Verify the message was updated
+  expect(updatedMessage).toBeDefined();
+  expect(updatedMessage?.messageContent).toBe(newMessageContent);
+
+  // Verify the message was updated in the database
+  const { ChatMessage } = await import("../../../src/models");
+  const messageInDb = await ChatMessage.findById(testMessage?._id);
+  expect(messageInDb?.messageContent).toBe(newMessageContent);

   spy.mockRestore();
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  it(`updates the chat message and returns it`, async () => {
    const { requestContext } = await import("../../../src/libraries");
    const spy = vi
      .spyOn(requestContext, "translate")
      .mockImplementationOnce((message) => message);

    const newMessageContent = "New Message";
    const args: MutationUpdateChatMessageArgs = {
      input: {
        messageContent: newMessageContent,
        chatId: testChat?.id,
        messageId: testMessage?._id.toString()
          ? testMessage?._id.toString()
          : "",
      },
    };
    const context = {
      userId: testMessage?.sender,
    };
    const { updateChatMessage: updateChatMessageResolver } = await import(
      "../../../src/resolvers/Mutation/updateChatMessage"
    );

    const updatedMessage = await updateChatMessageResolver?.({}, args, context);

    // Verify the message was updated
    expect(updatedMessage).toBeDefined();
    expect(updatedMessage?.messageContent).toBe(newMessageContent);

    // Verify the message was updated in the database
    const { ChatMessage } = await import("../../../src/models");
    const messageInDb = await ChatMessage.findById(testMessage?._id);
    expect(messageInDb?.messageContent).toBe(newMessageContent);

    spy.mockRestore();
  });
src/typeDefs/mutations.ts (2)

254-254: 🛠️ Refactor suggestion

Consider optimizing the markChatMessagesAsRead mutation.

The current implementation has a few potential improvements:

  1. The userId parameter seems redundant since the mutation is already authenticated with @auth. The user context could be used instead.
  2. Consider returning a more specific type (e.g., MarkMessagesAsReadPayload) that includes only the necessary fields instead of the entire Chat object.
-    markChatMessagesAsRead(chatId: ID!, userId: ID!): Chat @auth
+    markChatMessagesAsRead(chatId: ID!): MarkMessagesAsReadPayload @auth

Committable suggestion was skipped due to low confidence.


249-250: 💡 Codebase verification

Consider using the URL scalar type for the media field

The codebase already has a URL scalar type that's being used for media URLs in other parts of the schema (e.g., Advertisement's mediaUrl). For consistency and type safety:

  • Change media: String to media: URL in the sendMessageToChat mutation
  • This provides better type validation for URLs and maintains consistency with existing patterns in the codebase
🔗 Analysis chain

Consider adding input validation and documentation for media uploads.

While the changes support image sharing in chats, consider the following improvements:

  1. Add documentation comments describing accepted media formats and size limits
  2. Consider using a more specific type for media (e.g., URL scalar type) instead of generic String

Let's check if there are any existing custom scalar types we could use:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for custom scalar type definitions that might be suitable for media URLs
rg "scalar.*URL" --type ts

Length of output: 65


Script:

#!/bin/bash
# Let's check if URL scalar is already being used for media fields in the schema
rg "media.*URL" --type ts -A 2 -B 2

Length of output: 6374


Script:

#!/bin/bash
# Let's also check the scalar definition and its usage
cat src/typeDefs/scalars.ts

Length of output: 403


Script:

#!/bin/bash
# Check for any existing documentation or validation related to media
rg "media.*validation|validation.*media" --type ts

Length of output: 832

src/typeDefs/inputs.ts (1)

33-36: 🛠️ Refactor suggestion

Consider enhancing chat filtering capabilities.

The ChatWhereInput type could benefit from additional fields to support more comprehensive filtering:

  • organizationId for filtering chats by organization
  • isGroup for filtering between direct and group chats
  • name_starts_with for consistency with other filter types
 input ChatWhereInput {
   user: UserWhereInput
   name_contains: String
+  name_starts_with: String
+  organizationId: ID
+  isGroup: Boolean
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  input ChatWhereInput {
    user: UserWhereInput
    name_contains: String
    name_starts_with: String
    organizationId: ID
    isGroup: Boolean
  }
src/typeDefs/types.ts (4)

745-745: 🛠️ Refactor suggestion

Consider using a more type-safe approach instead of JSON.

The unseenMessagesByUsers field using JSON type might make it harder to validate the data structure and could lead to runtime errors. Consider creating a dedicated type for better type safety and documentation.

-    unseenMessagesByUsers: JSON
+    unseenMessagesByUsers: [UnseenMessages!]

Add this new type:

type UnseenMessages {
  user: User!
  messageIds: [ID!]!
}

754-754: 🛠️ Refactor suggestion

Enhance media field type safety and documentation.

The current media field is too generic. Consider:

  1. Using a more specific name to indicate it's for image URLs
  2. Adding validation for supported media types
-    media: String
+    imageUrl: URL

Or for better media type support:

type ChatMessageMedia {
  url: URL!
  type: MediaType!
}

enum MediaType {
  IMAGE
  VIDEO
  DOCUMENT
}

766-770: 🛠️ Refactor suggestion

Enhance message update capabilities.

The current input type has some limitations:

  1. No support for updating media content
  2. No validation for message content length
  3. No field to track edit history
  input UpdateChatMessageInput {
    chatId: ID!
-    messageContent: String!
+    messageContent: String! @constraint(minLength: 1, maxLength: 1000)
    messageId: ID!
+    media: ChatMessageMediaInput
  }

+ input ChatMessageMediaInput {
+   url: URL!
+   type: MediaType!
+ }

Also consider adding an editHistory field to the ChatMessage type to track message modifications.

Committable suggestion was skipped due to low confidence.


760-764: 🛠️ Refactor suggestion

Add URL validation for the image field.

Consider using the URL scalar type for the image field to ensure valid URLs are provided.

  input UpdateChatInput {
    _id: ID!
    name: String
-    image: String
+    image: URL
  }

Committable suggestion was skipped due to low confidence.

src/resolvers/Query/helperFunctions/getWhere.ts (1)

306-311: ⚠️ Potential issue

Fix duplicate name filter conditions

There are two conflicting conditions for where.name:

  1. A case-insensitive regex search at line 306
  2. An exact match at line 324

This creates ambiguity in the filter behavior, where the regex search will never execute because it will be overridden by the exact match condition.

Consolidate the conditions to ensure consistent behavior. Here's the suggested fix:

-  if (where.name) {
-    wherePayload = {
-      ...wherePayload,
-      name: { $regex: where.name, $options: "i" },
-    };
-  }

  // Returns provided name organization
  if (where.name) {
    wherePayload = {
      ...wherePayload,
-     name: where.name,
+     name: { $regex: where.name, $options: "i" },
    };
  }

Also applies to: 324-328

src/resolvers/Mutation/markChatMessagesAsRead.ts (3)

58-60: 🛠️ Refactor suggestion

Consider storing unseenMessagesByUsers as a native object

Currently, unseenMessagesByUsers is stored as a JSON string in the database, requiring parsing and stringifying during read and write operations. Storing it as a native object would improve efficiency and simplify the code.

To implement this refactor, remove unnecessary JSON.parse and JSON.stringify calls:

-const unseenMessagesByUsers = JSON.parse(
-  chat.unseenMessagesByUsers as unknown as string,
-);
+const unseenMessagesByUsers = chat.unseenMessagesByUsers as Record<string, number>;

...

           $set: {
-            unseenMessagesByUsers: JSON.stringify(unseenMessagesByUsers),
+            unseenMessagesByUsers: unseenMessagesByUsers,
           },

Also applies to: 74-75


62-66: ⚠️ Potential issue

Replace map with forEach for side-effect iteration

Using map without utilizing its returned array is inefficient and may cause confusion. Since you are performing an operation for its side effects, forEach is more appropriate.

Apply this diff to correct the iteration method:

-Object.keys(unseenMessagesByUsers).map((user: string) => {
+Object.keys(unseenMessagesByUsers).forEach((user: string) => {
  if (user === context.userId) {
    unseenMessagesByUsers[user] = 0;
  }
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    Object.keys(unseenMessagesByUsers).forEach((user: string) => {
      if (user === context.userId) {
        unseenMessagesByUsers[user] = 0;
      }
    });

10-18: ⚠️ Potential issue

Correct the function description in the JSDoc comment

The JSDoc comment describes sending a message to a direct chat, but this function actually marks chat messages as read. Please update the comment to accurately reflect the function's purpose.

Apply this diff to correct the JSDoc comment:

/**
- * This function enables to send message to direct chat.
+ * Marks chat messages as read for the current user in 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 direct chat exists.
+ * 1. If the chat exists.
 * 2. If the user exists
+ * 3. If the user is a member of the chat.
- * @returns Direct chat message.
+ * @returns Updated chat object.
 */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

/**
 * Marks chat messages as read for the current user in 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 chat exists.
 * 2. If the user exists
 * 3. If the user is a member of the chat.
 * @returns Updated chat object.
 */
src/resolvers/Mutation/sendMessageToChat.ts (4)

50-59: ⚠️ Potential issue

Enhance media input validation and add test coverage.

The media handling logic checks the prefix of args.media to determine the media type. Consider improving validation to ensure that args.media is a properly formatted data URL and to mitigate potential security risks from malformed inputs.

Additionally, the new media processing code is not covered by tests. Please add unit tests to cover image and video uploads, as well as the error case for unsupported file types.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 51-58: src/resolvers/Mutation/sendMessageToChat.ts#L51-L58
Added lines #L51 - L58 were not covered by tests


71-74: ⚠️ Potential issue

Refine type handling for unseenMessagesByUsers.

Casting chat.unseenMessagesByUsers as unknown as string may indicate type inconsistencies. Consider updating the type definitions to avoid unnecessary casting and ensure type safety. Also, ensure that chat.unseenMessagesByUsers is properly defined to prevent potential runtime errors when parsing.


90-93: 🛠️ Refactor suggestion

Consider storing unseenMessagesByUsers as an object in the database.

Storing unseenMessagesByUsers as a JSON string adds complexity and overhead due to the need for JSON.stringify and JSON.parse. Consider updating the database schema to store this field as an object directly, which can improve performance and simplify the code.


75-79: 🛠️ Refactor suggestion

Use .forEach instead of .map for side effects.

The .map method is intended for transforming arrays and returning a new array, but here it's used for side effects without utilizing the returned array. Replace .map with .forEach for clarity and to reflect that the code is iterating for side effects.

Apply this diff to make the change:

- Object.keys(unseenMessagesByUsers).map((user: string) => {
+ Object.keys(unseenMessagesByUsers).forEach((user: string) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  Object.keys(unseenMessagesByUsers).forEach((user: string) => {
    if (user !== context.userId) {
      unseenMessagesByUsers[user] += 1;
    }
  });
src/resolvers/Mutation/updateChat.ts (5)

67-72: ⚠️ Potential issue

Use Appropriate Error Class for Authorization Failures

Throwing a NotFoundError when the user is not authorized might mislead clients and hinder proper error handling.

Consider using ForbiddenError to accurately represent authorization errors:

- throw new errors.NotFoundError(
+ throw new errors.ForbiddenError(
    requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE),
    USER_NOT_AUTHORIZED_ERROR.CODE,
    USER_NOT_AUTHORIZED_ERROR.PARAM,
  );

This ensures that the error message and HTTP status code correctly reflect the nature of the error, improving client-side handling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    throw new errors.ForbiddenError(
      requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE),
      USER_NOT_AUTHORIZED_ERROR.CODE,
      USER_NOT_AUTHORIZED_ERROR.PARAM,
    );
  }

78-79: ⚠️ Potential issue

Add Error Handling for Image Upload Failures

The uploadEncodedImage function might throw an error if the image upload fails, but currently, there's no error handling in place.

Consider wrapping the upload in a try-catch block to handle potential errors:

if (existingchat.isGroup === true && args.input.image) {
+ try {
    uploadMediaFile = await uploadEncodedImage(args.input.image, null);
+ } catch (error) {
+   throw new errors.InternalServerError(
+     'Failed to upload image.',
+     'IMAGE_UPLOAD_ERROR',
+   );
+ }
}

This provides clearer feedback to the client and prevents unhandled exceptions from breaking the application.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    try {
      uploadMediaFile = await uploadEncodedImage(args.input.image, null);
    } catch (error) {
      throw new errors.InternalServerError(
        'Failed to upload image.',
        'IMAGE_UPLOAD_ERROR',
      );
    }

41-59: 🛠️ Refactor suggestion

Simplify User Retrieval Logic for Better Readability

The current logic for fetching currentUser involves multiple steps and checks, which can be streamlined to improve readability and maintainability.

Consider refactoring as follows:

- 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.NotFoundError(
-     requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE),
-     USER_NOT_FOUND_ERROR.CODE,
-     USER_NOT_FOUND_ERROR.PARAM,
-   );
- }
+ const currentUser = await findOrCreateCachedUser(context.userId);
+ if (!currentUser) {
+   throw new errors.NotFoundError(
+     requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE),
+     USER_NOT_FOUND_ERROR.CODE,
+     USER_NOT_FOUND_ERROR.PARAM,
+   );
+ }

Create a helper function findOrCreateCachedUser(userId) that handles fetching the user from cache or database and caching them if necessary. This reduces code duplication and enhances clarity.

Committable suggestion was skipped due to low confidence.


81-84: ⚠️ Potential issue

Ensure Accurate Fields Update Logic

The current logic for fieldsToUpdate might overwrite the image field incorrectly if args.input.image is not provided.

Consider modifying the logic to ensure that the image field is only updated when a new image is uploaded:

const fieldsToUpdate = {
  ...args.input,
- image: args.input.image ? uploadMediaFile : existingchat.image,
+ ...(uploadMediaFile ? { image: uploadMediaFile } : {}),
};

This way, if no new image is provided, the existing image remains unchanged without overwriting it with undefined.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  // Prepare fields to update
  const fieldsToUpdate = {
    ...args.input,
    ...(uploadMediaFile ? { image: uploadMediaFile } : {}),
  };

87-99: ⚠️ Potential issue

Handle Potential null Value After Updating Chat

There's a possibility that updatedChat could be null if the chat no longer exists or the update operation fails.

Add a check to handle this scenario:

const updatedChat = await Chat.findOneAndUpdate(
  // existing parameters
).lean();

+ if (!updatedChat) {
+   throw new errors.NotFoundError(
+     requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE),
+     CHAT_NOT_FOUND_ERROR.CODE,
+     CHAT_NOT_FOUND_ERROR.PARAM,
+   );
+ }

return updatedChat as InterfaceChat;

This ensures that the function does not return null, which could lead to unexpected errors downstream.

Committable suggestion was skipped due to low confidence.

src/resolvers/Mutation/updateChatMessage.ts (2)

106-106: ⚠️ Potential issue

Validate and sanitize messageContent before updating

To prevent potential security risks, ensure that args.input.messageContent is properly validated and sanitized before updating the database.


85-89: 💡 Codebase verification

⚠️ Potential issue

Use UnauthorizedError for authorization failures

The codebase has UnauthorizedError defined in src/libraries/errors/unauthorizedError.ts which is the appropriate error type to use for authorization failures. The suggested change to use UnauthorizedError instead of NotFoundError is correct.

🔗 Analysis chain

Use appropriate error type for authorization failures

Throwing a NotFoundError when the user is not authorized may be misleading. Consider using an UnauthorizedError or ForbiddenError to accurately represent the authorization error.

Apply this diff to use the appropriate error type:

-    throw new errors.NotFoundError(
+    throw new errors.UnauthorizedError(
       requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE),
       USER_NOT_AUTHORIZED_ERROR.CODE,
       USER_NOT_AUTHORIZED_ERROR.PARAM,
     );

Run the following script to verify if UnauthorizedError exists in the errors module:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if UnauthorizedError exists in the errors module.

# Expected: Should find UnauthorizedError or ForbiddenError defined.
rg 'class (UnauthorizedError|ForbiddenError)' -t ts -A 5

Length of output: 648

src/resolvers/Mutation/addUserToGroupChat.ts (5)

13-27: ⚠️ Potential issue

Synchronize function comments with code implementation

The function comments mention args.input.chatId, args.input.userId, and args.input.organizationId, but the code uses args.chatId and args.userId, and does not utilize organizationId.

Please update the comments to reflect the actual parameters used in the code, or adjust the code to align with the comments.


21-22: ⚠️ Potential issue

Update or implement missing functionality

The comments specify:

  • Step 5: "Ensures that the organization specified by args.input.organizationId exists."
  • Step 6: "Adds the user to the chat's admins list."

However, the current code does not implement these steps. Additionally, in step 6, the code adds the user to the users list instead of the admins list.

Please verify whether these steps are required. If they are, implement the necessary code; otherwise, update the comments to accurately describe the function's behavior.


101-113: ⚠️ Potential issue

Correct misleading comments and variable names

The comments at lines 101 and 113 refer to "Ad" instead of "chat":

  • Line 101: // Creates new Ad.
  • Line 113: // Returns createdAd.

These appear to be copy-paste errors. Please update the comments to accurately reflect the operation:

  • Line 101: // Adds the user to the chat.
  • Line 113: // Returns the updated chat.

77-80: 🛠️ Refactor suggestion

Simplify admin check logic

The current admin check uses map and includes to compare IDs:

if (
  !chat.admins
    .map((admin) => admin.toString())
    .includes(currentUser._id.toString())
) {
  // ...
}

This can be simplified using the some method with equals for object ID comparison.

Apply this diff to enhance readability:

 if (
-  !chat.admins
-    .map((admin) => admin.toString())
-    .includes(currentUser._id.toString())
+  !chat.admins.some((admin) => admin.equals(currentUser._id))
 ) {
  // ...
}

102-111: ⚠️ Potential issue

Ensure findOneAndUpdate returns the updated document

By default, findOneAndUpdate returns the document before the update. To return the updated document, include the option { new: true }.

Apply this diff to fix the issue:

 const updatedChat = await Chat.findOneAndUpdate(
   {
     _id: chat._id,
   },
   {
     $push: {
       users: args.userId,
     },
   },
+  {
+    new: true,
+  },
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const updatedChat = await Chat.findOneAndUpdate(
      {
        _id: chat._id,
      },
      {
        $push: {
          users: args.userId,
        },
      },
      {
        new: true,
      },
    );
schema.graphql (7)

209-209: 🛠️ Refactor suggestion

Consider defining a specific type instead of using JSON for unseenMessagesByUsers

Using JSON as the type for unseenMessagesByUsers may reduce type safety and clarity in your schema. Consider defining a specific type to represent the unseen messages per user to improve type safety and facilitate better code maintenance.


219-219: 🛠️ Refactor suggestion

Use the URL scalar type instead of String for media if it represents a URL

If the media field represents a URL to the media content, consider using the existing URL scalar type to improve type safety and clarity.


1160-1160: ⚠️ Potential issue

Ensure that at least one of messageContent or media is required

In the sendMessageToChat mutation, both messageContent and media are optional. This could allow sending messages without content or media, resulting in empty messages. Consider enforcing that at least one of messageContent or media must be provided.


1491-1491: 🛠️ Refactor suggestion

Ensure consistent use of user ID in chat queries

The chatsByUserId query accepts an id parameter, whereas getGroupChatsByUserId and getUnreadChatsByUserId do not. For consistency and better security practices, consider inferring the user ID from the authentication context in all chat queries and removing the explicit id parameter from chatsByUserId.

Also applies to: 1515-1515, 1519-1519


1713-1717: 🛠️ Refactor suggestion

Use id instead of _id in UpdateChatInput for consistency

In UpdateChatInput, consider using id: ID! instead of _id: ID! to maintain consistency with other input types in the schema.


1719-1723: ⚠️ Potential issue

Include media field and adjust nullability in UpdateChatMessageInput

The UpdateChatMessageInput lacks the media field and requires messageContent. To allow updating both text and media content of a message, consider adding media: String to the input and making messageContent optional, similar to the sendMessageToChat mutation.


1126-1126: ⚠️ Potential issue

Avoid passing userId as a parameter; infer it from authentication context

Passing userId as a parameter in markChatMessagesAsRead could lead to security issues, as users might mark messages as read on behalf of others. Consider inferring the userId from the authenticated user context instead.

Apply this diff to adjust the mutation signature:

-markChatMessagesAsRead(chatId: ID!, userId: ID!): Chat
+markChatMessagesAsRead(chatId: ID!): Chat
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  markChatMessagesAsRead(chatId: ID!): Chat
src/types/generatedGraphQLTypes.ts (4)

282-282: 🛠️ Refactor suggestion

Consider defining a specific type for 'unseenMessagesByUsers'

Using Scalars['JSON']['output'] for unseenMessagesByUsers may reduce type safety. Consider defining a specific interface or type to represent the structure of this field for better clarity and type checking.


293-293: 🛠️ Refactor suggestion

Use a more specific scalar type for 'media' field

The media field in ChatMessage is of type String. If it represents a URL, consider using the URL scalar type to enhance type safety and validation.


2802-2806: 🛠️ Refactor suggestion

Add missing fields to 'UpdateChatInput'

The UpdateChatInput type lacks fields for updating other chat properties such as admins or users. If intended, consider adding these fields to allow full chat updates.


1743-1744: ⚠️ Potential issue

Ensure at least one of 'media' or 'messageContent' is required in 'sendMessageToChat'

Currently, both media and messageContent are optional, which could allow sending empty messages. To prevent this, ensure that at least one of these fields is required.

Consider updating the mutation input to enforce this requirement:

 export type MutationSendMessageToChatArgs = {
   chatId: Scalars['ID']['input'];
-  media?: InputMaybe<Scalars['String']['input']>;
-  messageContent?: InputMaybe<Scalars['String']['input']>;
+  media?: InputMaybe<Scalars['String']['input']>;
+  messageContent?: InputMaybe<Scalars['String']['input']>;
+  /** At least one of 'media' or 'messageContent' is required */
+  _atLeastOneOfMediaOrMessageContent: Scalars['Boolean']['input'];
   replyTo?: InputMaybe<Scalars['ID']['input']>;
 };

Alternatively, add validation in the resolver to check that at least one of media or messageContent is provided.

Committable suggestion was skipped due to low confidence.

Copy link

github-actions bot commented Nov 9, 2024

This pull request did not get any activity in the past 10 days and will be closed in 180 days if no update occurs. Please verify it has no conflicts with the develop branch and rebase if needed. Mention it now if you need help or give permission to other people to finish your work.

@github-actions github-actions bot added the no-pr-activity No pull request activity label Nov 9, 2024
@palisadoes
Copy link
Contributor

During the week of November 11, 2024 we will start a code freeze on the develop branches in Talawa, Talawa Admin and Talawa-API.

We have completed a project to convert the Talawa-API backend to use PostgreSQL. Work will then begin with us merging code in the develop branches to a new develop-postrgres branch in each repository.

Planning activities for this will be managed in our #talawa-projects slack channel. A GitHub project will be created to track specially labeled issues. We completed a similar exercise last year using a similar methodology.

Starting November 12, California time no new PRs will be accepted against the develop branch. They must be applied to the develop-postrgres branch.

There are some GSoC project features that will need to be merged into develop. These will be the only exceptions.

This activity and the post GSoC 2024 start date was announced in our #general Slack channel last month as a pinned post.

@palisadoes
Copy link
Contributor

Please fix the conflicting files and tests

@github-actions github-actions bot removed the no-pr-activity No pull request activity label Nov 11, 2024
Copy link

This pull request did not get any activity in the past 10 days and will be closed in 180 days if no update occurs. Please verify it has no conflicts with the develop branch and rebase if needed. Mention it now if you need help or give permission to other people to finish your work.

@github-actions github-actions bot added no-pr-activity No pull request activity and removed no-pr-activity No pull request activity labels Nov 21, 2024
@palisadoes
Copy link
Contributor

@disha1202 Are you still working on this?

Copy link

github-actions bot commented Dec 4, 2024

This pull request did not get any activity in the past 10 days and will be closed in 180 days if no update occurs. Please verify it has no conflicts with the develop branch and rebase if needed. Mention it now if you need help or give permission to other people to finish your work.

@github-actions github-actions bot added no-pr-activity No pull request activity and removed no-pr-activity No pull request activity labels Dec 4, 2024
@Cioppolo14
Copy link
Contributor

Closing this as inactive.

@Cioppolo14 Cioppolo14 closed this Dec 13, 2024
@palisadoes
Copy link
Contributor

Reopening. GSoC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants