Repository: RocketChat/Rocket.Chat
Pull request #35273: fix: CodeSettingInput renders duplicate code text box  
Author: login: abhinavkrin
Labels: name: stat: ready to merge
description: PR tested and approved waiting for merge
name: stat: QA assured
description: Means it has been tested and approved by a company insider
Created: 2025-02-20T13:25:51Z | Merged: 2025-03-21T16:08:50Z

<!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. -->

<!-- Your Pull Request name should start with one of the following tags
  feat: Adding a new feature
  refactor: A code change that doesn't change behavior (it doesn't add anything and doesn't fix anything)
  fix: For bug fixes that affect the end-user
  chore: For small tasks
  docs: For documentation
  ci: For updating CI configuration
  test: For adding tests
  i18n: For updating any translations
  regression: Issues created/reported/fixed during the development phase. kind of problem that never existed in production and that we don't need to list in a changelog for the end user
-->

<!-- Checklist!!! If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code. 
  - I have read the Contributing Guide - https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat doc
  - I have signed the CLA - https://cla-assistant.io/RocketChat/Rocket.Chat
  - Lint and unit tests pass locally with my changes
  - I have added tests that prove my fix is effective or that my feature works (if applicable)
  - I have added necessary documentation (if applicable)
  - Any dependent changes have been merged and published in downstream modules
-->

## Proposed changes (including videos or screenshots)
<!--
  Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.
  If it fixes a bug or resolves a feature request, be sure to link to that issue below.
  This description won't be displayed to our end users in the release notes, so feel free to add as much technical context as needed.
  If the changes introduced in this pull request must be presented in the release notes, make sure to add a changeset file. Check our guidelines for adding a changeset to your pull request: https://developer.rocket.chat/contribute-to-rocket.chat/modes-of-contribution/participate-in-rocket.chat-development/development-workflow#4.-adding-changeset-to-your-pull-request 
-->
This PR fixes an issue where the `CodeSettingInput` component renders the code text box twice.  

The CodeMirror setup process is not instantaneous, causing a second call to create a duplicate code editor. To prevent this, a ref is used to track if an initialization is already in progress, ensuring it runs only once.  

*Before:*
<img width="1101" alt="Screenshot 2025-02-20 at 6 54 26 PM" src="https://github.com/user-attachments/assets/7877a94b-2b69-4562-9d15-bd518ed7133d" />

*After:*
<img width="1108" alt="Screenshot 2025-02-20 at 6 54 58 PM" src="https://github.com/user-attachments/assets/d53aa9aa-f1c8-4d33-bdfc-727152593563" />


## Issue(s)
<!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 -->

## Steps to test or reproduce
<!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable -->

## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->
[CORE-944](https://rocketchat.atlassian.net/browse/CORE-994)

[CORE-944]: https://rocketchat.atlassian.net/browse/CORE-944?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---

### Pull Request Description

This pull request addresses an issue in the Rocket.Chat repository where the `CodeSettingInput` component was rendering duplicate code text boxes. The changes include:

- **Fix**: The introduction of a `settingUpRef` to prevent multiple initializations of the CodeMirror component, which was causing the duplicate text boxes.
- **Improvement**: Enhanced cleanup logic by verifying the existence of the parent node before invoking the `toTextArea` method, ensuring proper resource management and preventing potential errors.

These changes are implemented in the `CodeMirror.tsx` file and are documented in the changeset file `honest-toys-guess.md`. The source branch for this fix is `fix/code-setting-input-duplicate-textbox`, and it targets the `develop` branch.


Diff:
diff --git a/.changeset/honest-toys-guess.md b/.changeset/honest-toys-guess.md
new file mode 100644
index 0000000000000..67fae4cb61c43
--- /dev/null
+++ b/.changeset/honest-toys-guess.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Fixes an issue where the code input type in settings renders duplicate code text boxes.  
diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
index 1f249c7373c64..bef8372819197 100644
--- a/apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
+++ b/apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
@@ -1,7 +1,7 @@
 import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
 import type { Editor, EditorFromTextArea } from 'codemirror';
 import type { ReactElement } from 'react';
-import { useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 
 const defaultGutters = ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'];
 
@@ -44,77 +44,69 @@ function CodeMirror({
 	...props
 }: CodeMirrorProps): ReactElement {
 	const [value, setValue] = useState(valueProp || defaultValue);
-
-	const textAreaRef = useRef<HTMLTextAreaElement>(null);
-	const editorRef = useRef<EditorFromTextArea | null>(null);
 	const handleChange = useEffectEvent(onChange);
 
-	useEffect(() => {
-		if (editorRef.current) {
-			return;
-		}
-
-		const setupCodeMirror = async (): Promise<void> => {
-			const { default: CodeMirror } = await import('codemirror');
-			await Promise.all([
-				import('../../../../../../../app/ui/client/lib/codeMirror/codeMirror'),
-				import('codemirror/addon/edit/matchbrackets'),
-				import('codemirror/addon/edit/closebrackets'),
-				import('codemirror/addon/edit/matchtags'),
-				import('codemirror/addon/edit/trailingspace'),
-				import('codemirror/addon/search/match-highlighter'),
-				import('codemirror/lib/codemirror.css'),
-			]);
-
-			if (!textAreaRef.current) {
-				return;
-			}
-
-			editorRef.current = CodeMirror.fromTextArea(textAreaRef.current, {
-				lineNumbers,
-				lineWrapping,
-				mode,
-				gutters,
-				foldGutter,
-				matchBrackets,
-				autoCloseBrackets,
-				matchTags,
-				showTrailingSpace,
-				highlightSelectionMatches,
-				readOnly,
-			});
-
-			editorRef.current.on('change', (doc: Editor) => {
-				const value = doc.getValue();
-				setValue(value);
-				handleChange(value);
-			});
-		};
-
-		setupCodeMirror();
-
-		return (): void => {
-			if (!editorRef.current) {
-				return;
+	const editorRef = useRef<EditorFromTextArea | null>(null);
+	const textAreaRef = useCallback(
+		async (node: HTMLTextAreaElement | null) => {
+			if (!node) return;
+
+			try {
+				const { default: CodeMirror } = await import('codemirror');
+				await Promise.all([
+					import('../../../../../../../app/ui/client/lib/codeMirror/codeMirror'),
+					import('codemirror/addon/edit/matchbrackets'),
+					import('codemirror/addon/edit/closebrackets'),
+					import('codemirror/addon/edit/matchtags'),
+					import('codemirror/addon/edit/trailingspace'),
+					import('codemirror/addon/search/match-highlighter'),
+					import('codemirror/lib/codemirror.css'),
+				]);
+
+				editorRef.current = CodeMirror.fromTextArea(node, {
+					lineNumbers,
+					lineWrapping,
+					mode,
+					gutters,
+					foldGutter,
+					matchBrackets,
+					autoCloseBrackets,
+					matchTags,
+					showTrailingSpace,
+					highlightSelectionMatches,
+					readOnly,
+				});
+
+				editorRef.current.on('change', (doc: Editor) => {
+					const newValue = doc.getValue();
+					setValue(newValue);
+					handleChange(newValue);
+				});
+
+				return () => {
+					if (node.parentNode) {
+						editorRef.current?.toTextArea();
+					}
+				};
+			} catch (error) {
+				console.error('CodeMirror initialization failed:', error);
 			}
-
-			editorRef.current.toTextArea();
-		};
-	}, [
-		autoCloseBrackets,
-		foldGutter,
-		gutters,
-		highlightSelectionMatches,
-		lineNumbers,
-		lineWrapping,
-		matchBrackets,
-		matchTags,
-		mode,
-		handleChange,
-		readOnly,
-		textAreaRef,
-		showTrailingSpace,
-	]);
+		},
+		[
+			autoCloseBrackets,
+			foldGutter,
+			gutters,
+			highlightSelectionMatches,
+			lineNumbers,
+			lineWrapping,
+			matchBrackets,
+			matchTags,
+			mode,
+			handleChange,
+			readOnly,
+			showTrailingSpace,
+		],
+	);
 
 	useEffect(() => {
 		setValue(valueProp);
diff --git a/apps/meteor/tests/e2e/administration-settings.spec.ts b/apps/meteor/tests/e2e/administration-settings.spec.ts
index d2996d6eac886..24ffa09d34c1c 100644
--- a/apps/meteor/tests/e2e/administration-settings.spec.ts
+++ b/apps/meteor/tests/e2e/administration-settings.spec.ts
@@ -1,6 +1,6 @@
 import { Users } from './fixtures/userStates';
 import { Admin } from './page-objects';
-import { getSettingValueById } from './utils';
+import { getSettingValueById, setSettingValueById } from './utils';
 import { test, expect } from './utils/test';
 
 test.use({ storageState: Users.admin.state });
@@ -42,11 +42,29 @@ test.describe.parallel('administration-settings', () => {
 			await page.goto('/admin/settings/Layout');
 		});
 
-		test('should code mirror full screen be displayed correctly', async ({ page }) => {
+		test.afterAll(async ({ api }) => setSettingValueById(api, 'theme-custom-css', ''));
+
+		test('should display the code mirror correctly', async ({ page, api }) => {
 			await poAdmin.getAccordionBtnByName('Custom CSS').click();
-			await poAdmin.btnFullScreen.click();
 
-			await expect(page.getByRole('code')).toHaveCSS('width', '920px');
+			await test.step('should render only one code mirror element', async () => {
+				const codeMirrorParent = page.getByRole('code');
+				await expect(codeMirrorParent.locator('.CodeMirror')).toHaveCount(1);
+			});
+
+			await test.step('should display full screen properly', async () => {
+				await poAdmin.btnFullScreen.click();
+				await expect(page.getByRole('code')).toHaveCSS('width', '920px');
+				await poAdmin.btnExitFullScreen.click();
+			});
+
+			await test.step('should reflect updated value when valueProp changes after server update', async () => {
+				const codeValue = `.test-class-${Date.now()} { background-color: red; }`;
+				await setSettingValueById(api, 'theme-custom-css', codeValue);
+
+				const codeMirrorParent = page.getByRole('code');
+				await expect(codeMirrorParent.locator('.CodeMirror-line')).toHaveText(codeValue);
+			});
 		});
 	});
 });
diff --git a/apps/meteor/tests/e2e/page-objects/admin.ts b/apps/meteor/tests/e2e/page-objects/admin.ts
index 49f86a59b6f9b..8c26f47a773b5 100644
--- a/apps/meteor/tests/e2e/page-objects/admin.ts
+++ b/apps/meteor/tests/e2e/page-objects/admin.ts
@@ -291,6 +291,10 @@ export class Admin {
 		return this.page.getByRole('button', { name: 'Full Screen', exact: true });
 	}
 
+	get btnExitFullScreen(): Locator {
+		return this.page.getByRole('button', { name: 'Exit Full Screen', exact: true });
+	}
+
 	async dropdownFilterRoomType(text = 'All rooms'): Promise<Locator> {
 		return this.page.locator(`div[role="button"]:has-text("${text}")`);
 	}


Reviews:
user: login: dougfabris
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-02-20T18:05:35Z
user: login: kody-ai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-10T14:03:52Z
user: login: kody-ai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-10T14:03:55Z
user: login: dougfabris
body: @abhinavkrin looking deeper to the code I think we could use a `callbackRef` instead of adding a third ref and `useEffect`. WDYT?
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-17T18:18:28Z
user: login: dougfabris
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-19T20:01:39Z
user: login: dougfabris
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-21T14:05:07Z

Review comments:
diff_hunk: @@ -0,0 +1,15 @@
+import { Users } from './fixtures/userStates';
+import { test, expect } from './utils/test';
+
+test.use({ storageState: Users.admin.state });
+
+test.describe.serial('code-setting-input-renders-one-text-area', () => {
+	test.beforeEach(async ({ page }) => {
+		await page.goto('/admin/settings/Message');
+	});
+
+	test('renders exactly one CodeMirror element', async ({ page }) => {
+		const textarea = page.locator('#Message_CustomFields ~ .CodeMirror');
path: apps/meteor/tests/e2e/code-setting-input-renders-one-text-area.spec.ts
user: login: dougfabris
body: this is not an appropriate locator
created_at: 2025-02-20T18:04:57Z
author_association: MEMBER
path: apps/meteor/tests/e2e/code-setting-input-renders-one-text-area.spec.ts
user: login: dougfabris
body: we already have a place where we run some test for this `CodeMirror`, under settings layout I think, can we add this there?
created_at: 2025-02-20T18:05:27Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,6 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Fixes an issue where the code input type in settings would render duplicate code text boxes.  
path: .changeset/honest-toys-guess.md
user: login: kody-ai[bot]
body: ![kody code-review](https://img.shields.io/badge/kody-code--review-brightgreen)![Documentation and Comments](https://img.shields.io/badge/Documentation_and_Comments-D81B60)

```typescript
Fixes an issue where the code input type in settings would render duplicate code text boxes by addressing the component rendering logic in the settings module.
```
Consider adding more context about the root cause and how the issue was fixed to improve maintainability and understanding for future developers.



<sub>Talk to Kody by mentioning @kody</sub>

<sub>Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.</sub><!-- kody-codereview -->&#8203;
&#8203;
created_at: 2025-03-10T14:03:52Z
author_association: NONE
diff_hunk: @@ -91,15 +92,23 @@ function CodeMirror({
 			});
 		};
 
-		setupCodeMirror();
+		settingUpRef.current = true;
+		setupCodeMirror().then(() => {
+			settingUpRef.current = false;
+		});
path: apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
user: login: kody-ai[bot]
body: ![kody code-review](https://img.shields.io/badge/kody-code--review-brightgreen)![Error Handling](https://img.shields.io/badge/Error_Handling-FF6D00)

```typescript
setupCodeMirror().then(() => {
	settingUpRef.current = false;
}).catch((error) => {
	console.error('CodeMirror initialization failed:', error);
});
```
Consider adding error handling for the CodeMirror setup process to catch and handle potential import failures or initialization errors.



<sub>Talk to Kody by mentioning @kody</sub>

<sub>Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.</sub><!-- kody-codereview -->&#8203;
&#8203;
created_at: 2025-03-10T14:03:55Z
author_association: NONE
diff_hunk: @@ -91,15 +92,27 @@ function CodeMirror({
 			});
 		};
 
-		setupCodeMirror();
+		settingUpRef.current = true;
+		setupCodeMirror()
+			.then(() => {
+				settingUpRef.current = false;
+			})
+			.catch((error) => {
+				console.error('CodeMirror initialization failed:', error);
+			});
 
-		return (): void => {
+		const cleanp = () => {
 			if (!editorRef.current) {
 				return;
 			}
 
-			editorRef.current.toTextArea();
+			// Checking parent node to avoid error. A null parent node makes the toTextArea method throw an error.
path: apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
user: login: dougfabris
body: unnecessary comment

```suggestion

```
created_at: 2025-03-17T18:18:01Z
author_association: MEMBER
diff_hunk: @@ -44,91 +44,68 @@ function CodeMirror({
 	...props
 }: CodeMirrorProps): ReactElement {
 	const [value, setValue] = useState(valueProp || defaultValue);
-
-	const textAreaRef = useRef<HTMLTextAreaElement>(null);
-	const editorRef = useRef<EditorFromTextArea | null>(null);
 	const handleChange = useEffectEvent(onChange);
 
-	useEffect(() => {
-		if (editorRef.current) {
-			return;
-		}
-
-		const setupCodeMirror = async (): Promise<void> => {
-			const { default: CodeMirror } = await import('codemirror');
-			await Promise.all([
-				import('../../../../../../../app/ui/client/lib/codeMirror/codeMirror'),
-				import('codemirror/addon/edit/matchbrackets'),
-				import('codemirror/addon/edit/closebrackets'),
-				import('codemirror/addon/edit/matchtags'),
-				import('codemirror/addon/edit/trailingspace'),
-				import('codemirror/addon/search/match-highlighter'),
-				import('codemirror/lib/codemirror.css'),
-			]);
-
-			if (!textAreaRef.current) {
-				return;
-			}
-
-			editorRef.current = CodeMirror.fromTextArea(textAreaRef.current, {
-				lineNumbers,
-				lineWrapping,
-				mode,
-				gutters,
-				foldGutter,
-				matchBrackets,
-				autoCloseBrackets,
-				matchTags,
-				showTrailingSpace,
-				highlightSelectionMatches,
-				readOnly,
-			});
-
-			editorRef.current.on('change', (doc: Editor) => {
-				const value = doc.getValue();
-				setValue(value);
-				handleChange(value);
-			});
-		};
-
-		setupCodeMirror();
-
-		return (): void => {
-			if (!editorRef.current) {
-				return;
+	const textAreaRef = useCallback(
+		async (node: HTMLTextAreaElement | null) => {
+			if (!node) return;
+
+			try {
+				const { default: CodeMirror } = await import('codemirror');
+				await Promise.all([
+					import('../../../../../../../app/ui/client/lib/codeMirror/codeMirror'),
+					import('codemirror/addon/edit/matchbrackets'),
+					import('codemirror/addon/edit/closebrackets'),
+					import('codemirror/addon/edit/matchtags'),
+					import('codemirror/addon/edit/trailingspace'),
+					import('codemirror/addon/search/match-highlighter'),
+					import('codemirror/lib/codemirror.css'),
+				]);
+
+				const editor = CodeMirror.fromTextArea(node, {
+					lineNumbers,
+					lineWrapping,
+					mode,
+					gutters,
+					foldGutter,
+					matchBrackets,
+					autoCloseBrackets,
+					matchTags,
+					showTrailingSpace,
+					highlightSelectionMatches,
+					readOnly,
+				});
+
+				editor.on('change', (doc: Editor) => {
+					const newValue = doc.getValue();
+					setValue(newValue);
+					handleChange(newValue);
+				});
+
+				return () => {
+					if (node.parentNode) {
+						editor.toTextArea();
+					}
+				};
+			} catch (error) {
+				console.error('CodeMirror initialization failed:', error);
 			}
-
-			editorRef.current.toTextArea();
-		};
-	}, [
-		autoCloseBrackets,
-		foldGutter,
-		gutters,
-		highlightSelectionMatches,
-		lineNumbers,
-		lineWrapping,
-		matchBrackets,
-		matchTags,
-		mode,
-		handleChange,
-		readOnly,
-		textAreaRef,
-		showTrailingSpace,
-	]);
-
-	useEffect(() => {
path: apps/meteor/client/views/admin/settings/Setting/inputs/CodeMirror/CodeMirror.tsx
user: login: dougfabris
body: after changing the setting value, saving it and reloading, the `valueProp` is different from what is rendered in the CodeBox. Can u check it and add a test to guarantee this?
created_at: 2025-03-19T20:01:35Z
author_association: MEMBER

PR comments:
user: login: dionisio-bot[bot]
created_at: 2025-02-20T13:25:55Z
body: Looks like this PR is not ready to merge, because of the following issues:
- This PR is targeting the wrong base branch. It should target 7.6.0, but it targets 7.5.0

Please fix the issues and try again

If you have any trouble, please check the [PR guidelines](https://handbook.rocket.chat/departments-and-operations/research-and-development/engineering/development/pr-general-instructions-and-handling)
author_association: CONTRIBUTOR
user: login: changeset-bot[bot]
created_at: 2025-02-20T13:25:55Z
body: ###  🦋  Changeset detected

Latest commit: da9a7e2e487a1fb30b44047dfc14e2b63e61d321

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 36 packages</summary>

  | Name                                | Type  |
| ----------------------------------- | ----- |
| @rocket.chat/meteor                 | Patch |
| @rocket.chat/core-typings           | Patch |
| @rocket.chat/rest-typings           | Patch |
| @rocket.chat/uikit-playground       | Patch |
| @rocket.chat/api-client             | Patch |
| @rocket.chat/apps                   | Patch |
| @rocket.chat/core-services          | Patch |
| @rocket.chat/cron                   | Patch |
| @rocket.chat/ddp-client             | Patch |
| @rocket.chat/freeswitch             | Patch |
| @rocket.chat/fuselage-ui-kit        | Patch |
| @rocket.chat/gazzodown              | Patch |
| @rocket.chat/livechat               | Patch |
| @rocket.chat/model-typings          | Patch |
| @rocket.chat/ui-contexts            | Patch |
| @rocket.chat/account-service        | Patch |
| @rocket.chat/authorization-service  | Patch |
| @rocket.chat/ddp-streamer           | Patch |
| @rocket.chat/omnichannel-transcript | Patch |
| @rocket.chat/presence-service       | Patch |
| @rocket.chat/queue-worker           | Patch |
| @rocket.chat/stream-hub-service     | Patch |
| @rocket.chat/license                | Patch |
| @rocket.chat/omnichannel-services   | Patch |
| @rocket.chat/pdf-worker             | Patch |
| @rocket.chat/presence               | Patch |
| rocketchat-services                 | Patch |
| @rocket.chat/models                 | Patch |
| @rocket.chat/network-broker         | Patch |
| @rocket.chat/mock-providers         | Patch |
| @rocket.chat/ui-avatar              | Patch |
| @rocket.chat/ui-client              | Patch |
| @rocket.chat/ui-video-conf          | Patch |
| @rocket.chat/ui-voip                | Patch |
| @rocket.chat/web-ui-registration    | Patch |
| @rocket.chat/instance-status        | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/RocketChat/Rocket.Chat/new/fix/code-setting-input-duplicate-textbox?filename=.changeset/blue-apples-act.md&value=---%0A%22%40rocket.chat%2Fmeteor%22%3A%20patch%0A---%0A%0Afix%3A%20CodeSettingInput%20renders%20duplicate%20code%20text%20box%20%20%0A)


author_association: NONE
user: login: abhinavkrin
created_at: 2025-02-20T13:32:08Z
body: I have created an e2e test instead of unit test since it was difficult to simulate the actual delay or runtime scenario to make the test fail in unit test. 
author_association: MEMBER
user: login: codecov[bot]
created_at: 2025-02-20T13:32:10Z
body: ## [Codecov](https://app.codecov.io/gh/RocketChat/Rocket.Chat/pull/35273?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 59.73%. Comparing base [(`bffc49f`)](https://app.codecov.io/gh/RocketChat/Rocket.Chat/commit/bffc49f426259925c415651c2b2a58083dac547a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat) to head [(`da9a7e2`)](https://app.codecov.io/gh/RocketChat/Rocket.Chat/commit/da9a7e2e487a1fb30b44047dfc14e2b63e61d321?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat).
> Report is 1 commits behind head on develop.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/RocketChat/Rocket.Chat/pull/35273/graphs/tree.svg?width=650&height=150&src=pr&token=lEAH159Fca&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat)](https://app.codecov.io/gh/RocketChat/Rocket.Chat/pull/35273?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat)

```diff
@@           Coverage Diff            @@
##           develop   #35273   +/-   ##
========================================
  Coverage    59.73%   59.73%           
========================================
  Files         2830     2830           
  Lines        68379    68379           
  Branches     15161    15161           
========================================
  Hits         40844    40844           
  Misses       24919    24919           
  Partials      2616     2616           
```

| [Flag](https://app.codecov.io/gh/RocketChat/Rocket.Chat/pull/35273/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat) | Coverage Δ | |
|---|---|---|
| [unit](https://app.codecov.io/gh/RocketChat/Rocket.Chat/pull/35273/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat) | `75.92% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=RocketChat#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: abhinavkrin
created_at: 2025-03-10T14:02:30Z
body: @kody start-review
author_association: MEMBER
user: login: kody-ai[bot]
created_at: 2025-03-10T14:02:37Z
body: ## Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.



<details>
<summary>Kody Guide: Usage and Configuration</summary>

<details>
<summary>Interacting with Kody</summary>

- **Request a Review:** Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

- **Provide Feedback:** Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

</details>

<details>
<summary>Current Kody Configuration</summary>

<details>
<summary>Review Options</summary>

The following review options are enabled or disabled:

| Options                        | Enabled |
|-------------------------------|---------|
| **Security** | ✅ |
| **Code Style** | ✅ |
| **Kody Rules** | ✅ |
| **Refactoring** | ✅ |
| **Error Handling** | ✅ |
| **Maintainability** | ✅ |
| **Potential Issues** | ✅ |
| **Documentation And Comments** | ✅ |
| **Performance And Optimization** | ✅ |

</details>

**[Access your configuration settings here.](https://app.kodus.io/automations/AutomationCodeReview/global/general)**

</details>
</details>

<!-- kody-codereview -->
&#8203;
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-10T14:17:13Z
body: [PR Preview Action](https://github.com/rossjrw/pr-preview-action) v1.6.0
:---:
| <p></p> :rocket: View preview at <br> https://RocketChat.github.io/Rocket.Chat/pr-preview/pr-35273/ <br><br>
| <h6>Built to branch [`gh-pages`](https://github.com/RocketChat/Rocket.Chat/tree/gh-pages) at 2025-03-21 14:33 UTC. <br> Preview will be ready when the [GitHub Pages deployment](https://github.com/RocketChat/Rocket.Chat/deployments) is complete. <br><br> </h6>
<!-- Sticky Pull Request Commentpr-preview -->
author_association: CONTRIBUTOR