Skip to content

chore: replace unsafe any in CannedResponseList onClickItem with proper type#39001

Open
Agarwalchetan wants to merge 3 commits intoRocketChat:developfrom
Agarwalchetan:fix/canned-response-list-onclickitem-typing
Open

chore: replace unsafe any in CannedResponseList onClickItem with proper type#39001
Agarwalchetan wants to merge 3 commits intoRocketChat:developfrom
Agarwalchetan:fix/canned-response-list-onclickitem-typing

Conversation

@Agarwalchetan
Copy link
Copy Markdown
Contributor

@Agarwalchetan Agarwalchetan commented Feb 24, 2026

Related Issue / Discussion

Resolves the existing // FIXME: fix typings comment in CannedResponseList.tsx.


Changes

  • Modified CannedResponseList.tsx

    • Replaced any in the onClickItem prop with the appropriate composite type already used in the same component.

Further Details

Summary

The onClickItem prop was previously defined as:

onClickItem: (data: any) => void; // FIXME: fix typings

This has been updated to use the same type as the elements of cannedItems defined in the same props interface:

onClickItem: (
  data: IOmnichannelCannedResponse & {
    departmentName?: ILivechatDepartment['name'];
  }
) => void;

The composite type matches:

cannedItems: (
  IOmnichannelCannedResponse & {
    departmentName?: ILivechatDepartment['name'];
  }
)[];

Impact

  • Removes unsafe any
  • Ensures strict TypeScript type safety
  • Maintains internal consistency within the component
  • Introduces no runtime changes

Compatibility

  • Existing callers already pass the correct shape
  • WrapCannedResponseList passes a stricter (non-optional) departmentName, which is structurally compatible
  • Tests use jest.fn() for onClickItem, which remains valid
  • No new TypeScript errors introduced

This PR strictly addresses the explicit FIXME comment and does not modify runtime behavior.

Summary by CodeRabbit

  • New Features
    • Added a back action to the canned responses list so users can navigate back to the canned-responses tab from a response view.
  • Refactor
    • Improved type and prop handling in the canned responses UI for more reliable interactions.
  • Tests
    • Updated tests and stories to cover the new back-action behavior.

COMM-144

@Agarwalchetan Agarwalchetan requested a review from a team as a code owner February 24, 2026 18:23
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Feb 24, 2026

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 8.4.0, but it targets 8.3.0

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Feb 24, 2026

⚠️ No Changeset found

Latest commit: 31be6ca

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 24, 2026

Walkthrough

Added a new back-action prop and narrowed the item click prop type across the canned responses list: onClickItem now expects IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] }, and onClickBack: MouseEventHandler<HTMLOrSVGElement> was introduced and passed through to wrap/list components.

Changes

Cohort / File(s) Summary
List component
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
Narrowed onClickItem type from any to (data: IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] }) => void and added onClickBack: MouseEventHandler<HTMLOrSVGElement> to props; passes onClickBack to wrap when rendering a single canned item.
Wrapper / wiring
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx
Made departmentName optional in handler data and added onClickBack handler that navigates back to the canned-responses tab; wires onClickBack into CannedResponseList.
Tests
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx
Updated test defaults to include onClickBack: jest.fn() to reflect the new prop surface.
Stories
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx
Added story args for onClickItem and onClickBack (actions) to enable UI interaction in Storybook.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
I hopped in to tidy the trail,
Gave clicks a shape and a tiny back-tail,
Now lists can return and items behave—
A rabbit's small fix, neat and brave! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title states 'chore' but the PR description and commit message indicate this is a 'fix' that resolves unsafe typing, and also introduces a new onClickBack prop beyond just type refinement. Clarify whether this is a 'chore' (refactor) or 'fix' (bug fix). Also consider whether the title should mention the onClickBack prop addition, which represents a functional change beyond type refinement.
✅ Passed checks (2 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx (1)

23-38: Consider extracting the repeated intersection type into a named alias.

The inline intersection IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] } is now duplicated verbatim on lines 25 (cannedItems) and 34 (onClickItem). A named alias keeps the two props obviously in sync and makes future type changes a single-point edit.

♻️ Proposed refactor: extract a shared type alias
+type CannedResponseItem = IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] };
+
 type CannedResponseListProps = {
   loadMoreItems: () => void;
-  cannedItems: (IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] })[];
+  cannedItems: CannedResponseItem[];
   itemCount: number;
   onClose: () => void;
   options: [string, string][];
   text: string;
   setText: FormEventHandler<HTMLInputElement>;
   type: string;
   setType: Dispatch<SetStateAction<string>>;
   isRoomOverMacLimit: boolean;
-  onClickItem: (data: IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] }) => void;
+  onClickItem: (data: CannedResponseItem) => void;
   onClickCreate: (e: MouseEvent<HTMLOrSVGElement>) => void;
   onClickUse: (e: MouseEvent<HTMLOrSVGElement>, text: string) => void;
   reload: () => void;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx`
around lines 23 - 38, The inline intersection type IOmnichannelCannedResponse &
{ departmentName?: ILivechatDepartment['name'] } is duplicated in the
CannedResponseListProps definition; extract it into a named alias (e.g.,
CannedResponseWithDepartment) and replace both cannedItems and onClickItem
signatures to use that alias so future changes are single-point edits and both
props stay in sync (update the type alias and references in the
CannedResponseListProps declaration).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx`:
- Around line 23-38: The inline intersection type IOmnichannelCannedResponse & {
departmentName?: ILivechatDepartment['name'] } is duplicated in the
CannedResponseListProps definition; extract it into a named alias (e.g.,
CannedResponseWithDepartment) and replace both cannedItems and onClickItem
signatures to use that alias so future changes are single-point edits and both
props stay in sync (update the type alias and references in the
CannedResponseListProps declaration).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55bf071 and 9fbede3.

📒 Files selected for processing (1)
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
🔇 Additional comments (1)
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx (1)

70-78: Type mismatch: onClickItem callback signature does not match onClickBack requirements.

onClickItem expects a data object (data: IOmnichannelCannedResponse & { departmentName?: ILivechatDepartment['name'] }) => void, but onClickBack is typed as MouseEventHandler<HTMLOrSVGElement> (i.e., (event: MouseEvent<HTMLOrSVGElement>) => void). Passing a data callback where an event handler is expected is a type incompatibility unrelated to contravariance of optional properties.

Likely an incorrect or invalid review comment.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Copy link
Copy Markdown
Contributor

@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

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx (1)

88-99: ⚠️ Potential issue | 🟡 Minor

Pre-existing test name contradicts its assertion.

The test is named should NOT render Create button when user has only save-department-canned-responses permission, but the assertion is expect(screen.getByText('Create')).toBeInTheDocument() — a positive assertion. Compare with line 115 which correctly pairs a "should NOT render" name with queryByText(...).not.toBeInTheDocument(). Either the test description needs to drop "NOT", or the assertion needs to flip to match the description.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx`
around lines 88 - 99, The test with description "should NOT render Create button
when user has only save-department-canned-responses permission" is contradictory
because it asserts expect(screen.getByText('Create')).toBeInTheDocument(); fix
by making the behavior and assertion consistent: either rename the test string
to "should render Create button when user has only
save-department-canned-responses permission" or change the assertion to
expect(screen.queryByText('Create')).not.toBeInTheDocument(); update the test
that calls render(<CannedResponseList {...defaultProps} />) with
mockAppRoot().withPermission('save-department-canned-responses') accordingly so
the test name and assertion match (adjust the string in the it(...) call or
replace getByText with queryByText + .not.toBeInTheDocument()).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx`:
- Around line 88-99: The test with description "should NOT render Create button
when user has only save-department-canned-responses permission" is contradictory
because it asserts expect(screen.getByText('Create')).toBeInTheDocument(); fix
by making the behavior and assertion consistent: either rename the test string
to "should render Create button when user has only
save-department-canned-responses permission" or change the assertion to
expect(screen.queryByText('Create')).not.toBeInTheDocument(); update the test
that calls render(<CannedResponseList {...defaultProps} />) with
mockAppRoot().withPermission('save-department-canned-responses') accordingly so
the test name and assertion match (adjust the string in the it(...) call or
replace getByText with queryByText + .not.toBeInTheDocument()).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9fbede3 and c2cf6a7.

📒 Files selected for processing (4)
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx
🧠 Learnings (1)
📚 Learning: 2026-02-24T19:36:47.551Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:47.551Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx
🔇 Additional comments (5)
apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.spec.tsx (1)

69-69: LGTM — onClickBack: jest.fn() correctly satisfies the new required prop.

apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList.tsx (1)

56-64: LGTM — onClickBack handler is correctly implemented.

Usage of useEffectEvent is consistent with the existing onClickItem pattern. Navigating without a context param correctly strips the canned-response detail context, returning to the list view.

apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.stories.tsx (1)

76-78: LGTM — story args correctly extended for the expanded public API.

apps/meteor/client/views/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx (2)

34-35: LGTM — type updates are clean and internally consistent.

onClickItem now matches the cannedItems element type (line 25) and onClickBack: MouseEventHandler<HTMLOrSVGElement> aligns with the handler signature in WrapCannedResponseList.tsx.


70-80: No issues found. WrapCannedResponse.tsx correctly declares onClickBack as a required prop (line 13 of its type definition) and does not declare onClickItem. The code in CannedResponseList.tsx properly passes onClickBack={onClickBack} without causing TypeScript errors.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 24, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 70.92%. Comparing base (2e6441e) to head (31be6ca).
⚠️ Report is 11 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #39001      +/-   ##
===========================================
- Coverage    70.98%   70.92%   -0.07%     
===========================================
  Files         3209     3209              
  Lines       113896   113900       +4     
  Branches     20677    20638      -39     
===========================================
- Hits         80844    80778      -66     
- Misses       30997    31064      +67     
- Partials      2055     2058       +3     
Flag Coverage Δ
e2e 60.43% <ø> (-0.13%) ⬇️
e2e-api 48.17% <ø> (-0.08%) ⬇️
unit 71.58% <85.71%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ggazzo ggazzo added this to the 8.3.0 milestone Feb 24, 2026
@ggazzo ggazzo changed the title fix: replace unsafe any in CannedResponseList onClickItem with proper type chore: replace unsafe any in CannedResponseList onClickItem with proper type Feb 25, 2026
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Feb 25, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Feb 25, 2026
@Agarwalchetan
Copy link
Copy Markdown
Contributor Author

Hi, just a gentle follow-up on this PR
Please let me know if any changes or clarifications are needed.
Happy to update accordingly.

@scuciatto scuciatto modified the milestones: 8.3.0, 8.4.0 Mar 25, 2026
@dionisio-bot dionisio-bot bot removed the stat: ready to merge PR tested and approved waiting for merge label Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community stat: QA assured Means it has been tested and approved by a company insider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants